Allow limit/sort/marker for resource listing

This commit is contained in:
Mehdi Abaakouk
2015-08-31 06:47:01 +00:00
committed by Mehdi Abaakouk
parent dd3fd5f35f
commit 2bed0c8314
3 changed files with 109 additions and 24 deletions

View File

@@ -19,6 +19,7 @@ from gnocchiclient.tests.functional import base
class ResourceClientTest(base.ClientTestBase):
RESOURCE_ID = str(uuid.uuid4())
RESOURCE_ID2 = str(uuid.uuid4())
PROJECT_ID = str(uuid.uuid4())
def details_multiple(self, output_lines, with_label=False):
@@ -96,17 +97,45 @@ class ResourceClientTest(base.ClientTestBase):
# Search
result = self.gnocchi('resource',
params="search generic --query 'project_id=%s'" %
self.PROJECT_ID)
params=("search generic "
"--query 'project_id=%s'"
) % self.PROJECT_ID)
resource_list = self.parser.listing(result)[0]
self.assertEqual(self.RESOURCE_ID, resource_list["id"])
self.assertEqual(self.PROJECT_ID, resource_list["project_id"])
self.assertEqual(resource["started_at"], resource_list["started_at"])
# CREATE 2
result = self.gnocchi(
'resource', params=("create generic "
"-a id:%s "
"-a project_id:%s"
) % (self.RESOURCE_ID2, self.PROJECT_ID))
resource2 = self.details_multiple(result)[0]
self.assertEqual(self.RESOURCE_ID2, resource2["id"])
self.assertEqual(self.PROJECT_ID, resource2["project_id"])
self.assertNotEqual('None', resource2["started_at"])
# Search + limit + short
result = self.gnocchi('resource',
params=("search generic "
"--query 'project_id=%s' "
"--sort started_at:asc "
"--marker %s "
"--limit 1"
) % (self.PROJECT_ID, self.RESOURCE_ID))
resource_limit = self.parser.listing(result)[0]
self.assertEqual(self.RESOURCE_ID2, resource_limit["id"])
self.assertEqual(self.PROJECT_ID, resource_limit["project_id"])
self.assertEqual(resource2["started_at"], resource_limit["started_at"])
# DELETE
result = self.gnocchi('resource',
params="delete %s" % self.RESOURCE_ID)
self.assertEqual("", result)
result = self.gnocchi('resource',
params="delete %s" % self.RESOURCE_ID2)
self.assertEqual("", result)
# GET FAIL
result = self.gnocchi('resource',
@@ -124,5 +153,6 @@ class ResourceClientTest(base.ClientTestBase):
# LIST EMPTY
result = self.gnocchi('resource', params="list generic")
self.assertNotIn(self.RESOURCE_ID,
[r['id'] for r in self.parser.listing(result)])
resource_ids = [r['id'] for r in self.parser.listing(result)]
self.assertNotIn(self.RESOURCE_ID, resource_ids)
self.assertNotIn(self.RESOURCE_ID2, resource_ids)

View File

@@ -12,12 +12,30 @@
# under the License.
from oslo_serialization import jsonutils
from six.moves.urllib import parse as urllib_parse
from gnocchiclient.v1 import base
def _get_pagination_options(details=False, history=False,
limit=None, marker=None, sorts=None):
options = []
if details:
options.append("details=true")
if history:
options.append("history=true")
if limit:
options.append("limit=%d" % limit)
if marker:
options.append("marker=%s" % urllib_parse.quote(marker))
for sort in sorts or []:
options.append("sort=%s" % urllib_parse.quote(sort))
return "&".join(options)
class ResourceManager(base.Manager):
def list(self, resource_type="generic", details=False, history=False):
def list(self, resource_type="generic", details=False, history=False,
limit=None, marker=None, sorts=None):
"""List resources
:param resource_type: Type of the resource
@@ -26,11 +44,16 @@ class ResourceManager(base.Manager):
:type details: bool
:param history: Show the history of resources
:type history: bool
:param limit: maximum number of resources to return
:type limit: int
:param marker: the last item of the previous page; we returns the next
results after this value.
:param sorts: list of resource attributes to order by. (example
["user_id:desc-nullslast", "project_id:asc"]
:type sorts: list of str
"""
details = "true" if details else "false"
history = "true" if history else "false"
url = self.client._build_url("resource/%s?details=%s&history=%s" % (
resource_type, details, history))
qs = _get_pagination_options(details, history, limit, marker, sorts)
url = self.client._build_url("resource/%s?%s" % (resource_type, qs))
return self.client.api.get(url).json()
def get(self, resource_type, resource_id, history=False):
@@ -48,7 +71,8 @@ class ResourceManager(base.Manager):
resource_type, resource_id, history))
return self.client.api.get(url).json()
def history(self, resource_type, resource_id, details=False):
def history(self, resource_type, resource_id, details=False,
limit=None, marker=None, sorts=None):
"""Get a resource
:param resource_type: Type of the resource
@@ -57,10 +81,17 @@ class ResourceManager(base.Manager):
:type resource_id: str
:param details: Show all attributes of resources
:type details: bool
:param limit: maximum number of resources to return
:type limit: int
:param marker: the last item of the previous page; we returns the next
results after this value.
:param sorts: list of resource attributes to order by. (example
["user_id:desc-nullslast", "project_id:asc"]
:type sorts: list of str
"""
details = "true" if details else "false"
url = self.client._build_url("resource/%s/%s/history?details=%s" % (
resource_type, resource_id, details))
qs = _get_pagination_options(details, False, limit, marker, sorts)
url = self.client._build_url("resource/%s/%s/history?%s" % (
resource_type, resource_id, qs))
return self.client.api.get(url).json()
def create(self, resource_type, resource):
@@ -103,7 +134,7 @@ class ResourceManager(base.Manager):
self.client.api.delete(url)
def search(self, resource_type="generic", request=None, details=False,
history=False):
history=False, limit=None, marker=None, sorts=None):
"""List resources
:param resource_type: Type of the resource
@@ -114,6 +145,13 @@ class ResourceManager(base.Manager):
:type details: bool
:param history: Show the history of resources
:type history: bool
:param limit: maximum number of resources to return
:type limit: int
:param marker: the last item of the previous page; we returns the next
results after this value.
:param sorts: list of resource attributes to order by. (example
["user_id:desc-nullslast", "project_id:asc"]
:type sorts: list of str
See Gnocchi REST API documentation for the format
of *request dictionary*
@@ -121,11 +159,9 @@ class ResourceManager(base.Manager):
"""
request = request or {}
details = "true" if details else "false"
history = "true" if history else "false"
qs = _get_pagination_options(details, False, limit, marker, sorts)
url = self.client._build_url(
"/search/resource/%s?details=%s&history=%s" % (
resource_type, details, history))
"/search/resource/%s?%s" % (resource_type, qs))
return self.client.api.post(
url, headers={'Content-Type': "application/json"},
data=jsonutils.dumps(request)).json()

View File

@@ -33,6 +33,15 @@ class CliResourceList(lister.Lister):
if history:
parser.add_argument("--history", action='store_true',
help="Show history of the resources"),
parser.add_argument("--limit", type=int, metavar="<LIMIT>",
help=("Number of resources to return "
"(Default is server default)"))
parser.add_argument("--marker", metavar="<MARKER>",
help=("Last item of the previous listing. "
"Return the next results after this value"))
parser.add_argument("--sort", action="append", metavar="<SORT>",
help=("Sort of resource attribute ",
"(example: user_id:desc-nullslast"))
parser.add_argument("resource_type",
default="generic",
nargs='?',
@@ -42,10 +51,21 @@ class CliResourceList(lister.Lister):
def take_action(self, parsed_args):
resources = self.app.client.resource.list(
resource_type=parsed_args.resource_type,
details=parsed_args.details,
history=parsed_args.history)
**self._get_pagination_options(parsed_args))
return self.COLS, [self._resource2tuple(r) for r in resources]
@staticmethod
def _get_pagination_options(parsed_args):
options = dict(
details=parsed_args.details,
sorts=parsed_args.sort,
limit=parsed_args.limit,
marker=parsed_args.marker)
if hasattr(parsed_args, 'history'):
options['history'] = parsed_args.history
return options
@classmethod
def _resource2tuple(cls, resource):
return tuple([resource[k] for k in cls.COLS])
@@ -63,7 +83,7 @@ class CliResourceHistory(CliResourceList):
resources = self.app.client.resource.history(
resource_type=parsed_args.resource_type,
resource_id=parsed_args.resource_id,
details=parsed_args.details)
**self._get_pagination_options(parsed_args))
return self.COLS, [self._resource2tuple(r) for r in resources]
@@ -77,9 +97,8 @@ class CliResourceSearch(CliResourceList):
def take_action(self, parsed_args):
resources = self.app.client.resource.search(
resource_type=parsed_args.resource_type,
details=parsed_args.details,
history=parsed_args.history,
request=utils.search_query_builder(parsed_args.query))
request=utils.search_query_builder(parsed_args.query),
**self._get_pagination_options(parsed_args))
return self.COLS, [self._resource2tuple(r) for r in resources]