v3 Catalog
- v3 catalog tests (bug 1023933) - v3 catalog implementation (bug 1023938) Change-Id: Ie118819d25afbff62327ffc8be5b5fda2ef7f4ed
This commit is contained in:
parent
64452c6b55
commit
ff669f0da9
@ -24,11 +24,7 @@ class Catalog(kvs.Base, catalog.Driver):
|
||||
def get_catalog(self, user_id, tenant_id, metadata=None):
|
||||
return self.db.get('catalog-%s-%s' % (tenant_id, user_id))
|
||||
|
||||
def get_service(self, service_id):
|
||||
return self.db.get('service-%s' % service_id)
|
||||
|
||||
def list_services(self):
|
||||
return self.db.get('service_list', [])
|
||||
# service crud
|
||||
|
||||
def create_service(self, service_id, service):
|
||||
self.db.set('service-%s' % service_id, service)
|
||||
@ -37,16 +33,53 @@ class Catalog(kvs.Base, catalog.Driver):
|
||||
self.db.set('service_list', list(service_list))
|
||||
return service
|
||||
|
||||
def list_services(self):
|
||||
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):
|
||||
self.db.set('service-%s' % service_id, service)
|
||||
return 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.get_service(endpoint['service_id'])
|
||||
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):
|
||||
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):
|
||||
self.db.set('endpoint-%s' % endpoint_id, endpoint)
|
||||
return 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)
|
||||
|
@ -52,22 +52,25 @@ class Catalog(sql.Base, catalog.Driver):
|
||||
# Services
|
||||
def list_services(self):
|
||||
session = self.get_session()
|
||||
services = session.query(Service)
|
||||
return [s['id'] for s in list(services)]
|
||||
services = session.query(Service).all()
|
||||
return [s.to_dict() for s in list(services)]
|
||||
|
||||
def _get_service(self, session, service_id):
|
||||
try:
|
||||
return session.query(Service).filter_by(id=service_id).one()
|
||||
except sql.NotFound:
|
||||
raise exception.ServiceNotFound(service_id=service_id)
|
||||
|
||||
def get_service(self, service_id):
|
||||
session = self.get_session()
|
||||
service_ref = session.query(Service).filter_by(id=service_id).first()
|
||||
if not service_ref:
|
||||
raise exception.ServiceNotFound(service_id=service_id)
|
||||
return service_ref.to_dict()
|
||||
return self._get_service(session, service_id).to_dict()
|
||||
|
||||
def delete_service(self, service_id):
|
||||
session = self.get_session()
|
||||
with session.begin():
|
||||
ref = self._get_service(session, service_id)
|
||||
session.query(Endpoint).filter_by(service_id=service_id).delete()
|
||||
if not session.query(Service).filter_by(id=service_id).delete():
|
||||
raise exception.ServiceNotFound(service_id=service_id)
|
||||
session.delete(ref)
|
||||
session.flush()
|
||||
|
||||
def create_service(self, service_id, service_ref):
|
||||
@ -78,6 +81,18 @@ class Catalog(sql.Base, catalog.Driver):
|
||||
session.flush()
|
||||
return service.to_dict()
|
||||
|
||||
def update_service(self, service_id, service_ref):
|
||||
session = self.get_session()
|
||||
with session.begin():
|
||||
ref = self._get_service(session, service_id)
|
||||
old_dict = ref.to_dict()
|
||||
old_dict.update(service_ref)
|
||||
new_service = Service.from_dict(old_dict)
|
||||
ref.type = new_service.type
|
||||
ref.extra = new_service.extra
|
||||
session.flush()
|
||||
return ref.to_dict()
|
||||
|
||||
# Endpoints
|
||||
def create_endpoint(self, endpoint_id, endpoint_ref):
|
||||
session = self.get_session()
|
||||
@ -95,18 +110,33 @@ class Catalog(sql.Base, catalog.Driver):
|
||||
raise exception.EndpointNotFound(endpoint_id=endpoint_id)
|
||||
session.flush()
|
||||
|
||||
def _get_endpoint(self, session, endpoint_id):
|
||||
try:
|
||||
return session.query(Endpoint).filter_by(id=endpoint_id).one()
|
||||
except sql.NotFound:
|
||||
raise exception.EndpointNotFound(endpoint_id=endpoint_id)
|
||||
|
||||
def get_endpoint(self, endpoint_id):
|
||||
session = self.get_session()
|
||||
endpoint_ref = session.query(Endpoint)
|
||||
endpoint_ref = endpoint_ref.filter_by(id=endpoint_id).first()
|
||||
if not endpoint_ref:
|
||||
raise exception.EndpointNotFound(endpoint_id=endpoint_id)
|
||||
return endpoint_ref.to_dict()
|
||||
return self._get_endpoint(session, endpoint_id).to_dict()
|
||||
|
||||
def list_endpoints(self):
|
||||
session = self.get_session()
|
||||
endpoints = session.query(Endpoint)
|
||||
return [e['id'] for e in list(endpoints)]
|
||||
return [e.to_dict() for e in list(endpoints)]
|
||||
|
||||
def update_endpoint(self, endpoint_id, endpoint_ref):
|
||||
session = self.get_session()
|
||||
with session.begin():
|
||||
ref = self._get_endpoint(session, endpoint_id)
|
||||
old_dict = ref.to_dict()
|
||||
old_dict.update(endpoint_ref)
|
||||
new_endpoint = Endpoint.from_dict(old_dict)
|
||||
ref.service_id = new_endpoint.service_id
|
||||
ref.region = new_endpoint.region
|
||||
ref.extra = new_endpoint.extra
|
||||
session.flush()
|
||||
return ref.to_dict()
|
||||
|
||||
def get_catalog(self, user_id, tenant_id, metadata=None):
|
||||
d = dict(CONF.iteritems())
|
||||
@ -114,8 +144,7 @@ class Catalog(sql.Base, catalog.Driver):
|
||||
'user_id': user_id})
|
||||
catalog = {}
|
||||
|
||||
endpoints = [self.get_endpoint(e)
|
||||
for e in self.list_endpoints()]
|
||||
endpoints = self.list_endpoints()
|
||||
for ep in endpoints:
|
||||
service = self.get_service(ep['service_id'])
|
||||
srv_type = service['type']
|
||||
|
@ -116,14 +116,6 @@ class Driver(object):
|
||||
raise exception.NotImplemented()
|
||||
|
||||
def list_services(self):
|
||||
"""List all service ids in catalog.
|
||||
|
||||
:returns: list of service_ids or an empty list.
|
||||
|
||||
"""
|
||||
raise exception.NotImplemented()
|
||||
|
||||
def get_all_services(self):
|
||||
"""List all services.
|
||||
|
||||
:returns: list of service_refs or an empty list.
|
||||
@ -176,14 +168,6 @@ class Driver(object):
|
||||
raise exception.NotImplemented()
|
||||
|
||||
def list_endpoints(self):
|
||||
"""List all endpoint ids in catalog.
|
||||
|
||||
:returns: list of endpoint_ids or an empty list.
|
||||
|
||||
"""
|
||||
raise exception.NotImplemented()
|
||||
|
||||
def get_all_endpoints(self):
|
||||
"""List all endpoints.
|
||||
|
||||
:returns: list of endpoint_refs or an empty list.
|
||||
@ -242,14 +226,10 @@ class ServiceController(wsgi.Application):
|
||||
self.token_api = token.Manager()
|
||||
super(ServiceController, self).__init__()
|
||||
|
||||
# CRUD extensions
|
||||
# NOTE(termie): this OS-KSADM stuff is not very consistent
|
||||
def get_services(self, context):
|
||||
self.assert_admin(context)
|
||||
service_list = self.catalog_api.list_services(context)
|
||||
service_refs = [self.catalog_api.get_service(context, x)
|
||||
for x in service_list]
|
||||
return {'OS-KSADM:services': service_refs}
|
||||
return {'OS-KSADM:services': service_list}
|
||||
|
||||
def get_service(self, context, service_id):
|
||||
self.assert_admin(context)
|
||||
@ -281,9 +261,7 @@ class EndpointController(wsgi.Application):
|
||||
def get_endpoints(self, context):
|
||||
self.assert_admin(context)
|
||||
endpoint_list = self.catalog_api.list_endpoints(context)
|
||||
endpoint_refs = [self.catalog_api.get_endpoint(context, e)
|
||||
for e in endpoint_list]
|
||||
return {'endpoints': endpoint_refs}
|
||||
return {'endpoints': endpoint_list}
|
||||
|
||||
def create_endpoint(self, context, endpoint):
|
||||
self.assert_admin(context)
|
||||
@ -312,7 +290,7 @@ class ServiceControllerV3(controller.V3Controller):
|
||||
def list_services(self, context):
|
||||
self.assert_admin(context)
|
||||
|
||||
refs = self.catalog_api.get_all_services(context)
|
||||
refs = self.catalog_api.list_services(context)
|
||||
refs = self._filter_by_attribute(context, refs, 'type')
|
||||
return {'services': self._paginate(context, refs)}
|
||||
|
||||
@ -351,7 +329,7 @@ class EndpointControllerV3(controller.V3Controller):
|
||||
def list_endpoints(self, context):
|
||||
self.assert_admin(context)
|
||||
|
||||
refs = self.catalog_api.get_all_endpoints(context)
|
||||
refs = self.catalog_api.list_endpoints(context)
|
||||
refs = self._filter_by_attribute(context, refs, 'service_id')
|
||||
refs = self._filter_by_attribute(context, refs, 'interface')
|
||||
return {'endpoints': self._paginate(context, refs)}
|
||||
|
@ -863,7 +863,7 @@ class CatalogTests(object):
|
||||
|
||||
# list
|
||||
services = self.catalog_api.list_services()
|
||||
self.assertIn(service_id, services)
|
||||
self.assertIn(service_id, [x['id'] for x in services])
|
||||
|
||||
# delete
|
||||
self.catalog_api.delete_service(service_id)
|
||||
@ -872,6 +872,30 @@ class CatalogTests(object):
|
||||
self.assertRaises(exception.ServiceNotFound,
|
||||
self.catalog_man.get_service, {}, service_id)
|
||||
|
||||
def test_delete_service_with_endpoint(self):
|
||||
# create a service
|
||||
service = {
|
||||
'id': uuid.uuid4().hex,
|
||||
'type': uuid.uuid4().hex,
|
||||
'name': uuid.uuid4().hex,
|
||||
'description': uuid.uuid4().hex,
|
||||
}
|
||||
self.catalog_api.create_service(service['id'], service)
|
||||
|
||||
# create an endpoint attached to the service
|
||||
endpoint = {
|
||||
'id': uuid.uuid4().hex,
|
||||
'service_id': service['id'],
|
||||
}
|
||||
self.catalog_api.create_endpoint(endpoint['id'], endpoint)
|
||||
|
||||
# deleting the service should also delete the endpoint
|
||||
self.catalog_api.delete_service(service['id'])
|
||||
self.assertRaises(exception.EndpointNotFound,
|
||||
self.catalog_man.get_endpoint, {}, endpoint['id'])
|
||||
self.assertRaises(exception.EndpointNotFound,
|
||||
self.catalog_man.delete_endpoint, {}, endpoint['id'])
|
||||
|
||||
def test_get_service_404(self):
|
||||
self.assertRaises(exception.ServiceNotFound,
|
||||
self.catalog_man.get_service,
|
||||
@ -890,18 +914,21 @@ class CatalogTests(object):
|
||||
'service_id': uuid.uuid4().hex,
|
||||
}
|
||||
self.assertRaises(exception.ServiceNotFound,
|
||||
self.catalog_api.create_endpoint,
|
||||
self.catalog_man.create_endpoint,
|
||||
{},
|
||||
endpoint['id'],
|
||||
endpoint)
|
||||
|
||||
def test_get_endpoint_404(self):
|
||||
self.assertRaises(exception.EndpointNotFound,
|
||||
self.catalog_api.get_endpoint,
|
||||
self.catalog_man.get_endpoint,
|
||||
{},
|
||||
uuid.uuid4().hex)
|
||||
|
||||
def test_delete_endpoint_404(self):
|
||||
self.assertRaises(exception.EndpointNotFound,
|
||||
self.catalog_api.delete_endpoint,
|
||||
self.catalog_man.delete_endpoint,
|
||||
{},
|
||||
uuid.uuid4().hex)
|
||||
|
||||
|
||||
|
@ -68,19 +68,3 @@ class KvsCatalog(test.TestCase, test_backend.CatalogTests):
|
||||
def test_get_catalog(self):
|
||||
catalog_ref = self.catalog_api.get_catalog('foo', 'bar')
|
||||
self.assertDictEqual(catalog_ref, self.catalog_foobar)
|
||||
|
||||
def test_create_endpoint_404(self):
|
||||
self.assertRaises(exception.NotImplemented,
|
||||
self.catalog_api.create_endpoint,
|
||||
uuid.uuid4().hex,
|
||||
{})
|
||||
|
||||
def test_get_endpoint_404(self):
|
||||
self.assertRaises(exception.NotImplemented,
|
||||
self.catalog_api.get_endpoint,
|
||||
uuid.uuid4().hex)
|
||||
|
||||
def test_delete_endpoint_404(self):
|
||||
self.assertRaises(exception.NotImplemented,
|
||||
self.catalog_api.delete_endpoint,
|
||||
uuid.uuid4().hex)
|
||||
|
@ -15,7 +15,6 @@
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from keystone import catalog
|
||||
from keystone.catalog.backends import templated as catalog_templated
|
||||
@ -67,19 +66,3 @@ class TestTemplatedCatalog(test.TestCase, test_backend.CatalogTests):
|
||||
'http://localhost:$(compute_port)s/v1.1/$(tenant)s'
|
||||
with self.assertRaises(exception.MalformedEndpoint):
|
||||
self.catalog_api.get_catalog('fake-user', 'fake-tenant')
|
||||
|
||||
def test_create_endpoint_404(self):
|
||||
self.assertRaises(exception.NotImplemented,
|
||||
self.catalog_api.create_endpoint,
|
||||
uuid.uuid4().hex,
|
||||
{})
|
||||
|
||||
def test_get_endpoint_404(self):
|
||||
self.assertRaises(exception.NotImplemented,
|
||||
self.catalog_api.get_endpoint,
|
||||
uuid.uuid4().hex)
|
||||
|
||||
def test_delete_endpoint_404(self):
|
||||
self.assertRaises(exception.NotImplemented,
|
||||
self.catalog_api.delete_endpoint,
|
||||
uuid.uuid4().hex)
|
||||
|
@ -711,7 +711,7 @@ class KeystoneClientTests(object):
|
||||
self.assertEquals(service_type, service.type)
|
||||
self.assertEquals(service_desc, service.description)
|
||||
|
||||
# update is not supported...
|
||||
# update is not supported in API v2...
|
||||
|
||||
# delete & read
|
||||
client.services.delete(id=service.id)
|
||||
@ -736,10 +736,9 @@ class KeystoneClientTests(object):
|
||||
id=uuid.uuid4().hex)
|
||||
|
||||
def test_endpoint_delete_404(self):
|
||||
# the catalog backend is expected to return Not Implemented
|
||||
from keystoneclient import exceptions as client_exceptions
|
||||
client = self.get_client(admin=True)
|
||||
self.assertRaises(client_exceptions.HTTPNotImplemented,
|
||||
self.assertRaises(client_exceptions.NotFound,
|
||||
client.endpoints.delete,
|
||||
id=uuid.uuid4().hex)
|
||||
|
||||
|
143
tests/test_v3_catalog.py
Normal file
143
tests/test_v3_catalog.py
Normal file
@ -0,0 +1,143 @@
|
||||
import uuid
|
||||
|
||||
import test_v3
|
||||
|
||||
|
||||
class CatalogTestCase(test_v3.RestfulTestCase):
|
||||
"""Test service & endpoint CRUD"""
|
||||
|
||||
def setUp(self):
|
||||
super(CatalogTestCase, self).setUp()
|
||||
|
||||
self.service_id = uuid.uuid4().hex
|
||||
self.service = self.new_service_ref()
|
||||
self.service['id'] = self.service_id
|
||||
self.catalog_api.create_service(
|
||||
self.service_id,
|
||||
self.service.copy())
|
||||
|
||||
self.endpoint_id = uuid.uuid4().hex
|
||||
self.endpoint = self.new_endpoint_ref(service_id=self.service_id)
|
||||
self.endpoint['id'] = self.endpoint_id
|
||||
self.catalog_api.create_endpoint(
|
||||
self.endpoint_id,
|
||||
self.endpoint.copy())
|
||||
|
||||
# service validation
|
||||
|
||||
def assertValidServiceListResponse(self, resp, ref):
|
||||
return self.assertValidListResponse(
|
||||
resp,
|
||||
'services',
|
||||
self.assertValidService,
|
||||
ref)
|
||||
|
||||
def assertValidServiceResponse(self, resp, ref):
|
||||
return self.assertValidResponse(
|
||||
resp,
|
||||
'service',
|
||||
self.assertValidService,
|
||||
ref)
|
||||
|
||||
def assertValidService(self, entity, ref=None):
|
||||
self.assertIsNotNone(entity.get('type'))
|
||||
if ref:
|
||||
self.assertEqual(ref['type'], entity['type'])
|
||||
return entity
|
||||
|
||||
# endpoint validation
|
||||
|
||||
def assertValidEndpointListResponse(self, resp, ref):
|
||||
return self.assertValidListResponse(
|
||||
resp,
|
||||
'endpoints',
|
||||
self.assertValidEndpoint,
|
||||
ref)
|
||||
|
||||
def assertValidEndpointResponse(self, resp, ref):
|
||||
return self.assertValidResponse(
|
||||
resp,
|
||||
'endpoint',
|
||||
self.assertValidEndpoint,
|
||||
ref)
|
||||
|
||||
def assertValidEndpoint(self, entity, ref=None):
|
||||
self.assertIsNotNone(entity.get('interface'))
|
||||
self.assertIsNotNone(entity.get('service_id'))
|
||||
if ref:
|
||||
self.assertEqual(ref['interface'], entity['interface'])
|
||||
self.assertEqual(ref['service_id'], entity['service_id'])
|
||||
return entity
|
||||
|
||||
# service crud tests
|
||||
|
||||
def test_create_service(self):
|
||||
"""POST /services"""
|
||||
ref = self.new_service_ref()
|
||||
r = self.post(
|
||||
'/services',
|
||||
body={'service': ref})
|
||||
return self.assertValidServiceResponse(r, ref)
|
||||
|
||||
def test_list_services(self):
|
||||
"""GET /services"""
|
||||
r = self.get('/services')
|
||||
self.assertValidServiceListResponse(r, self.service)
|
||||
|
||||
def test_get_service(self):
|
||||
"""GET /services/{service_id}"""
|
||||
r = self.get('/services/%(service_id)s' % {
|
||||
'service_id': self.service_id})
|
||||
self.assertValidServiceResponse(r, self.service)
|
||||
|
||||
def test_update_service(self):
|
||||
"""PATCH /services/{service_id}"""
|
||||
service = self.new_service_ref()
|
||||
del service['id']
|
||||
r = self.patch('/services/%(service_id)s' % {
|
||||
'service_id': self.service_id},
|
||||
body={'service': service})
|
||||
self.assertValidServiceResponse(r, service)
|
||||
|
||||
def test_delete_service(self):
|
||||
"""DELETE /services/{service_id}"""
|
||||
self.delete('/services/%(service_id)s' % {
|
||||
'service_id': self.service_id})
|
||||
|
||||
# endpoint crud tests
|
||||
|
||||
def test_list_endpoints(self):
|
||||
"""GET /endpoints"""
|
||||
r = self.get('/endpoints')
|
||||
self.assertValidEndpointListResponse(r, self.endpoint)
|
||||
|
||||
def test_create_endpoint(self):
|
||||
"""POST /endpoints"""
|
||||
ref = self.new_endpoint_ref(service_id=self.service_id)
|
||||
r = self.post(
|
||||
'/endpoints',
|
||||
body={'endpoint': ref})
|
||||
self.assertValidEndpointResponse(r, ref)
|
||||
|
||||
def test_get_endpoint(self):
|
||||
"""GET /endpoints/{endpoint_id}"""
|
||||
r = self.get(
|
||||
'/endpoints/%(endpoint_id)s' % {
|
||||
'endpoint_id': self.endpoint_id})
|
||||
self.assertValidEndpointResponse(r, self.endpoint)
|
||||
|
||||
def test_update_endpoint(self):
|
||||
"""PATCH /endpoints/{endpoint_id}"""
|
||||
ref = self.new_endpoint_ref(service_id=self.service_id)
|
||||
del ref['id']
|
||||
r = self.patch(
|
||||
'/endpoints/%(endpoint_id)s' % {
|
||||
'endpoint_id': self.endpoint_id},
|
||||
body={'endpoint': ref})
|
||||
self.assertValidEndpointResponse(r, ref)
|
||||
|
||||
def test_delete_endpoint(self):
|
||||
"""DELETE /endpoints/{endpoint_id}"""
|
||||
self.delete(
|
||||
'/endpoints/%(endpoint_id)s' % {
|
||||
'endpoint_id': self.endpoint_id})
|
Loading…
Reference in New Issue
Block a user