feat(api): GET and HEAD methods on queue
To allow GET/HEAD /queues/a-queue gives users an intuitive approach to test whether the queue exits, while the URI above is returned as the Location header by a queue's PUT method. Implements: blueprint queue-get-and-head Fixes: bug #1207075 Change-Id: Iefd3236a739b1a5d959efb489fc2b966ee893599
This commit is contained in:
parent
5b1c447ba2
commit
47e3638f95
@ -113,7 +113,7 @@ class QueueBase(ControllerBase):
|
|||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def create(self, name, project=None):
|
def create(self, name, project=None):
|
||||||
"""Base method for queue creation
|
"""Base method for queue creation.
|
||||||
|
|
||||||
:param name: The queue name
|
:param name: The queue name
|
||||||
:param project: Project id
|
:param project: Project id
|
||||||
@ -122,6 +122,17 @@ class QueueBase(ControllerBase):
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def exists(self, name, project=None):
|
||||||
|
"""Base method for testing queue existence.
|
||||||
|
|
||||||
|
:param name: The queue name
|
||||||
|
:param project: Project id
|
||||||
|
:returns: True if a queue exists and False
|
||||||
|
if it does not.
|
||||||
|
"""
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def set_metadata(self, name, metadata, project=None):
|
def set_metadata(self, name, metadata, project=None):
|
||||||
"""Base method for updating a queue metadata.
|
"""Base method for updating a queue metadata.
|
||||||
|
@ -122,6 +122,10 @@ class QueueController(storage.QueueBase):
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@utils.raises_conn_error
|
||||||
|
def exists(self, name, project=None):
|
||||||
|
return self._col.find_one({'p': project, 'n': name}) is not None
|
||||||
|
|
||||||
@utils.raises_conn_error
|
@utils.raises_conn_error
|
||||||
def set_metadata(self, name, metadata, project=None):
|
def set_metadata(self, name, metadata, project=None):
|
||||||
rst = self._col.update({'p': project, 'n': name},
|
rst = self._col.update({'p': project, 'n': name},
|
||||||
|
@ -95,6 +95,15 @@ class QueueController(base.QueueBase):
|
|||||||
|
|
||||||
return self.driver.affected
|
return self.driver.affected
|
||||||
|
|
||||||
|
def exists(self, name, project):
|
||||||
|
if project is None:
|
||||||
|
project = ''
|
||||||
|
|
||||||
|
return self.driver.run('''
|
||||||
|
select id from Queues
|
||||||
|
where project = ? and name = ?
|
||||||
|
''', project, name).fetchone() is not None
|
||||||
|
|
||||||
def set_metadata(self, name, metadata, project):
|
def set_metadata(self, name, metadata, project):
|
||||||
if project is None:
|
if project is None:
|
||||||
project = ''
|
project = ''
|
||||||
|
@ -75,6 +75,9 @@ class QueueControllerTest(ControllerBaseTest):
|
|||||||
created = self.controller.create('test', project=self.project)
|
created = self.controller.create('test', project=self.project)
|
||||||
self.assertTrue(created)
|
self.assertTrue(created)
|
||||||
|
|
||||||
|
# Test Queue Existence
|
||||||
|
self.assertTrue(self.controller.exists('test', project=self.project))
|
||||||
|
|
||||||
# Test Queue retrieval
|
# Test Queue retrieval
|
||||||
metadata = self.controller.get_metadata('test', project=self.project)
|
metadata = self.controller.get_metadata('test', project=self.project)
|
||||||
self.assertEqual(metadata, {})
|
self.assertEqual(metadata, {})
|
||||||
@ -103,6 +106,9 @@ class QueueControllerTest(ControllerBaseTest):
|
|||||||
# Test Queue Deletion
|
# Test Queue Deletion
|
||||||
self.controller.delete('test', project=self.project)
|
self.controller.delete('test', project=self.project)
|
||||||
|
|
||||||
|
# Test Queue Existence
|
||||||
|
self.assertFalse(self.controller.exists('test', project=self.project))
|
||||||
|
|
||||||
# Test DoesNotExist Exception
|
# Test DoesNotExist Exception
|
||||||
with testing.expect(storage.exceptions.DoesNotExist):
|
with testing.expect(storage.exceptions.DoesNotExist):
|
||||||
self.controller.get_metadata('test', project=self.project)
|
self.controller.get_metadata('test', project=self.project)
|
||||||
|
@ -48,9 +48,9 @@ class QueueLifecycleBaseTest(base.TestBase):
|
|||||||
location = ('Location', '/v1/queues/gumshoe')
|
location = ('Location', '/v1/queues/gumshoe')
|
||||||
self.assertIn(location, self.srmock.headers)
|
self.assertIn(location, self.srmock.headers)
|
||||||
|
|
||||||
# Get on queues shouldn't work any more
|
# Ensure queue existence
|
||||||
self.simulate_get(path, project_id)
|
self.simulate_head(path, project_id)
|
||||||
self.assertEquals(self.srmock.status, falcon.HTTP_405)
|
self.assertEquals(self.srmock.status, falcon.HTTP_204)
|
||||||
|
|
||||||
# Add metadata
|
# Add metadata
|
||||||
doc = '{"messages": {"ttl": 600}}'
|
doc = '{"messages": {"ttl": 600}}'
|
||||||
@ -67,6 +67,10 @@ class QueueLifecycleBaseTest(base.TestBase):
|
|||||||
self.simulate_delete(path, project_id)
|
self.simulate_delete(path, project_id)
|
||||||
self.assertEquals(self.srmock.status, falcon.HTTP_204)
|
self.assertEquals(self.srmock.status, falcon.HTTP_204)
|
||||||
|
|
||||||
|
# Get non-existent queue
|
||||||
|
self.simulate_get(path, project_id)
|
||||||
|
self.assertEquals(self.srmock.status, falcon.HTTP_404)
|
||||||
|
|
||||||
# Get non-existent stats
|
# Get non-existent stats
|
||||||
self.simulate_get(path + '/stats', project_id)
|
self.simulate_get(path + '/stats', project_id)
|
||||||
self.assertEquals(self.srmock.status, falcon.HTTP_404)
|
self.assertEquals(self.srmock.status, falcon.HTTP_404)
|
||||||
|
@ -44,6 +44,9 @@ class QueueController(storage.QueueBase):
|
|||||||
def create(self, name, project=None):
|
def create(self, name, project=None):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def exists(self, name, project=None):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
def set_metadata(self, name, metadata, project=None):
|
def set_metadata(self, name, metadata, project=None):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
@ -49,6 +49,21 @@ class ItemResource(object):
|
|||||||
resp.status = falcon.HTTP_201 if created else falcon.HTTP_204
|
resp.status = falcon.HTTP_201 if created else falcon.HTTP_204
|
||||||
resp.location = req.path
|
resp.location = req.path
|
||||||
|
|
||||||
|
def on_head(self, req, resp, project_id, queue_name):
|
||||||
|
LOG.debug(_("Queue item exists - queue: %(queue)s, "
|
||||||
|
"project: %(project)s") %
|
||||||
|
{"queue": queue_name, "project": project_id})
|
||||||
|
|
||||||
|
if self.queue_controller.exists(queue_name,
|
||||||
|
project=project_id):
|
||||||
|
resp.status = falcon.HTTP_204
|
||||||
|
else:
|
||||||
|
resp.status = falcon.HTTP_404
|
||||||
|
|
||||||
|
resp.content_location = req.path
|
||||||
|
|
||||||
|
on_get = on_head
|
||||||
|
|
||||||
def on_delete(self, req, resp, project_id, queue_name):
|
def on_delete(self, req, resp, project_id, queue_name):
|
||||||
LOG.debug(_("Queue item DELETE - queue: %(queue)s, "
|
LOG.debug(_("Queue item DELETE - queue: %(queue)s, "
|
||||||
"project: %(project)s") %
|
"project: %(project)s") %
|
||||||
|
Loading…
Reference in New Issue
Block a user