add links to return values from API methods
add meter links to resource return values. add resource self link. Change-Id: I0c9802b57ebbb9aa852acd7fdec1c49df8883a64 Fixes: bug1048728
This commit is contained in:
parent
88afcdd45f
commit
89ab2f86de
@ -55,6 +55,10 @@ class _Base(wtypes.Base):
|
|||||||
def from_db_model(cls, m):
|
def from_db_model(cls, m):
|
||||||
return cls(**(m.as_dict()))
|
return cls(**(m.as_dict()))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_db_and_links(cls, m, links):
|
||||||
|
return cls(links=links, **(m.as_dict()))
|
||||||
|
|
||||||
def as_dict(self, db_model):
|
def as_dict(self, db_model):
|
||||||
valid_keys = inspect.getargspec(db_model.__init__)[0]
|
valid_keys = inspect.getargspec(db_model.__init__)[0]
|
||||||
if 'self' in valid_keys:
|
if 'self' in valid_keys:
|
||||||
@ -66,6 +70,25 @@ class _Base(wtypes.Base):
|
|||||||
getattr(self, k) != wsme.Unset)
|
getattr(self, k) != wsme.Unset)
|
||||||
|
|
||||||
|
|
||||||
|
class Link(_Base):
|
||||||
|
"""A link representation
|
||||||
|
"""
|
||||||
|
|
||||||
|
href = wtypes.text
|
||||||
|
"The url of a link"
|
||||||
|
|
||||||
|
rel = wtypes.text
|
||||||
|
"The name of a link"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def sample(cls):
|
||||||
|
return cls(href=('http://localhost:8777/v2/meters/volume?'
|
||||||
|
'q.field=resource_id&'
|
||||||
|
'q.value=bd9431c1-8d69-4ad3-803a-8d4a6b89fd36'),
|
||||||
|
rel='volume'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Query(_Base):
|
class Query(_Base):
|
||||||
"""Sample query filter.
|
"""Sample query filter.
|
||||||
"""
|
"""
|
||||||
@ -218,6 +241,15 @@ def _flatten_metadata(metadata):
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def _make_link(rel_name, url, type, type_arg, query=None):
|
||||||
|
query_str = ''
|
||||||
|
if query:
|
||||||
|
query_str = '?q.field=%s&q.value=%s' % (query['field'],
|
||||||
|
query['value'])
|
||||||
|
return Link(href=('%s/v2/%s/%s%s') % (url, type, type_arg, query_str),
|
||||||
|
rel=rel_name)
|
||||||
|
|
||||||
|
|
||||||
class Sample(_Base):
|
class Sample(_Base):
|
||||||
"""A single measurement for a given meter and resource.
|
"""A single measurement for a given meter and resource.
|
||||||
"""
|
"""
|
||||||
@ -496,6 +528,9 @@ class Resource(_Base):
|
|||||||
metadata = {wtypes.text: wtypes.text}
|
metadata = {wtypes.text: wtypes.text}
|
||||||
"Arbitrary metadata associated with the resource"
|
"Arbitrary metadata associated with the resource"
|
||||||
|
|
||||||
|
links = [Link]
|
||||||
|
"A list containing a self link and associated meter links"
|
||||||
|
|
||||||
def __init__(self, metadata={}, **kwds):
|
def __init__(self, metadata={}, **kwds):
|
||||||
metadata = _flatten_metadata(metadata)
|
metadata = _flatten_metadata(metadata)
|
||||||
super(Resource, self).__init__(metadata=metadata, **kwds)
|
super(Resource, self).__init__(metadata=metadata, **kwds)
|
||||||
@ -508,12 +543,30 @@ class Resource(_Base):
|
|||||||
timestamp=datetime.datetime.utcnow(),
|
timestamp=datetime.datetime.utcnow(),
|
||||||
metadata={'name1': 'value1',
|
metadata={'name1': 'value1',
|
||||||
'name2': 'value2'},
|
'name2': 'value2'},
|
||||||
|
links=[Link(href=('http://localhost:8777/v2/resources/'
|
||||||
|
'bd9431c1-8d69-4ad3-803a-8d4a6b89fd36'),
|
||||||
|
rel='self'),
|
||||||
|
Link(href=('http://localhost:8777/v2/meters/volume?'
|
||||||
|
'q.field=resource_id&'
|
||||||
|
'q.value=bd9431c1-8d69-4ad3-803a-'
|
||||||
|
'8d4a6b89fd36'),
|
||||||
|
rel='volume')],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class ResourcesController(rest.RestController):
|
class ResourcesController(rest.RestController):
|
||||||
"""Works on resources."""
|
"""Works on resources."""
|
||||||
|
|
||||||
|
def _resource_links(self, resource_id):
|
||||||
|
links = [_make_link('self', pecan.request.host_url, 'resources',
|
||||||
|
resource_id)]
|
||||||
|
for meter in pecan.request.storage_conn.get_meters(resource=
|
||||||
|
resource_id):
|
||||||
|
query = {'field': 'resource_id', 'value': resource_id}
|
||||||
|
links.append(_make_link(meter.name, pecan.request.host_url,
|
||||||
|
'meters', meter.name, query=query))
|
||||||
|
return links
|
||||||
|
|
||||||
@wsme_pecan.wsexpose(Resource, unicode)
|
@wsme_pecan.wsexpose(Resource, unicode)
|
||||||
def get_one(self, resource_id):
|
def get_one(self, resource_id):
|
||||||
"""Retrieve details about one resource.
|
"""Retrieve details about one resource.
|
||||||
@ -522,7 +575,8 @@ class ResourcesController(rest.RestController):
|
|||||||
"""
|
"""
|
||||||
r = list(pecan.request.storage_conn.get_resources(
|
r = list(pecan.request.storage_conn.get_resources(
|
||||||
resource=resource_id))[0]
|
resource=resource_id))[0]
|
||||||
return Resource.from_db_model(r)
|
return Resource.from_db_and_links(r,
|
||||||
|
self._resource_links(resource_id))
|
||||||
|
|
||||||
@wsme_pecan.wsexpose([Resource], [Query])
|
@wsme_pecan.wsexpose([Resource], [Query])
|
||||||
def get_all(self, q=[]):
|
def get_all(self, q=[]):
|
||||||
@ -532,7 +586,8 @@ class ResourcesController(rest.RestController):
|
|||||||
"""
|
"""
|
||||||
kwargs = _query_to_kwargs(q, pecan.request.storage_conn.get_resources)
|
kwargs = _query_to_kwargs(q, pecan.request.storage_conn.get_resources)
|
||||||
resources = [
|
resources = [
|
||||||
Resource.from_db_model(r)
|
Resource.from_db_and_links(r,
|
||||||
|
self._resource_links(r.resource_id))
|
||||||
for r in pecan.request.storage_conn.get_resources(**kwargs)]
|
for r in pecan.request.storage_conn.get_resources(**kwargs)]
|
||||||
return resources
|
return resources
|
||||||
|
|
||||||
|
@ -93,3 +93,10 @@ or::
|
|||||||
and finally, a JSON-based example::
|
and finally, a JSON-based example::
|
||||||
|
|
||||||
$ curl -X GET -H 'X-Auth-Token:<inserttokenhere>' -H 'Content-Type:application/json' -d '{"q":[{"field": "timestamp","op": "ge","value":"2013-04-01T13:34:17"}]}' http://localhost:8777/v2/meters
|
$ curl -X GET -H 'X-Auth-Token:<inserttokenhere>' -H 'Content-Type:application/json' -d '{"q":[{"field": "timestamp","op": "ge","value":"2013-04-01T13:34:17"}]}' http://localhost:8777/v2/meters
|
||||||
|
|
||||||
|
|
||||||
|
Links
|
||||||
|
=====
|
||||||
|
|
||||||
|
.. autotype:: ceilometer.api.controllers.v2.Link
|
||||||
|
:members:
|
||||||
|
@ -308,3 +308,34 @@ class TestListResources(FunctionalTest):
|
|||||||
[('display_name', 'test-server'),
|
[('display_name', 'test-server'),
|
||||||
('tag', 'self.counter'),
|
('tag', 'self.counter'),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_resource_meter_links(self):
|
||||||
|
counter1 = counter.Counter(
|
||||||
|
'instance',
|
||||||
|
'cumulative',
|
||||||
|
'',
|
||||||
|
1,
|
||||||
|
'user-id',
|
||||||
|
'project-id',
|
||||||
|
'resource-id',
|
||||||
|
timestamp=datetime.datetime(2012, 7, 2, 10, 40),
|
||||||
|
resource_metadata={'display_name': 'test-server',
|
||||||
|
'tag': 'self.counter',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
msg = meter.meter_message_from_counter(counter1,
|
||||||
|
cfg.CONF.metering_secret,
|
||||||
|
'test_list_resources',
|
||||||
|
)
|
||||||
|
self.conn.record_metering_data(msg)
|
||||||
|
|
||||||
|
data = self.get_json('/resources')
|
||||||
|
links = data[0]['links']
|
||||||
|
self.assertEqual(len(links), 2)
|
||||||
|
self.assertEqual(links[0]['rel'], 'self')
|
||||||
|
self.assertTrue((self.PATH_PREFIX + '/resources/resource-id')
|
||||||
|
in links[0]['href'])
|
||||||
|
self.assertEqual(links[1]['rel'], 'instance')
|
||||||
|
self.assertTrue((self.PATH_PREFIX + '/meters/instance?'
|
||||||
|
'q.field=resource_id&q.value=resource-id')
|
||||||
|
in links[1]['href'])
|
||||||
|
Loading…
Reference in New Issue
Block a user