Add support for GET /v2/dataframes API endpoint to the client
Support for the ``GET /v2/dataframes`` endpoint has been added to the client. A new ``dataframes get`` CLI command is also available. Story: 2005890 Task: 36384 Depends-On: https://review.opendev.org/#/c/679636 Change-Id: Idfe93025e0f740906d0f53f33547c7746fc15169
This commit is contained in:
parent
def535752f
commit
2a3dd279dc
|
@ -162,6 +162,11 @@ class CkDataframesTest(base.BaseFunctionalTest):
|
|||
has_output=False,
|
||||
)
|
||||
|
||||
def test_dataframes_get(self):
|
||||
# TODO(jferrieu): functional tests will be added in another
|
||||
# patch for `dataframes get`
|
||||
pass
|
||||
|
||||
|
||||
class OSCDataframesTest(CkDataframesTest):
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#
|
||||
import json
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from cloudkittyclient import exc
|
||||
from cloudkittyclient.tests.unit.v2 import base
|
||||
|
||||
|
@ -149,3 +151,22 @@ class TestDataframes(base.BaseAPIEndpointTestCase):
|
|||
self.assertRaises(
|
||||
exc.ArgumentRequired,
|
||||
self.dataframes.add_dataframes)
|
||||
|
||||
def test_get_dataframes(self):
|
||||
self.dataframes.get_dataframes()
|
||||
self.api_client.get.assert_called_once_with('/v2/dataframes')
|
||||
|
||||
def test_get_dataframes_with_pagination_args(self):
|
||||
self.dataframes.get_dataframes(offset=10, limit=10)
|
||||
try:
|
||||
self.api_client.get.assert_called_once_with(
|
||||
'/v2/dataframes?limit=10&offset=10')
|
||||
except AssertionError:
|
||||
self.api_client.get.assert_called_once_with(
|
||||
'/v2/dataframes?offset=10&limit=10')
|
||||
|
||||
def test_get_dataframes_filters(self):
|
||||
self.dataframes.get_dataframes(
|
||||
filters=OrderedDict([('one', 'two'), ('three', 'four')]))
|
||||
self.api_client.get.assert_called_once_with(
|
||||
'/v2/dataframes?filters=one%3Atwo%2Cthree%3Afour')
|
||||
|
|
|
@ -48,3 +48,30 @@ class DataframesManager(base.BaseManager):
|
|||
url,
|
||||
data=dataframes,
|
||||
)
|
||||
|
||||
def get_dataframes(self, **kwargs):
|
||||
"""Returns a paginated list of DataFrames.
|
||||
|
||||
This support filters and datetime framing.
|
||||
|
||||
:param offset: Index of the first dataframe that should be returned.
|
||||
:type offset: int
|
||||
:param limit: Maximal number of dataframes to return.
|
||||
:type limit: int
|
||||
:param filters: Optional dict of filters to select data on.
|
||||
:type filters: dict
|
||||
:param begin: Start of the period to gather data from
|
||||
:type begin: datetime.datetime
|
||||
:param end: End of the period to gather data from
|
||||
:type end: datetime.datetime
|
||||
"""
|
||||
kwargs['filters'] = ','.join(
|
||||
'{}:{}'.format(k, v) for k, v in
|
||||
(kwargs.get('filters', None) or {}).items()
|
||||
)
|
||||
|
||||
authorized_args = [
|
||||
'offset', 'limit', 'filters', 'begin', 'end']
|
||||
|
||||
url = self.get_url(None, kwargs, authorized_args=authorized_args)
|
||||
return self.api_client.get(url).json()
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
import argparse
|
||||
|
||||
from cliff import command
|
||||
from cliff import lister
|
||||
from oslo_utils import timeutils
|
||||
|
||||
from cloudkittyclient import utils
|
||||
|
||||
|
@ -40,3 +42,75 @@ class CliDataframesAdd(command.Command):
|
|||
utils.get_client_from_osc(self).dataframes.add_dataframes(
|
||||
dataframes=dataframes,
|
||||
)
|
||||
|
||||
|
||||
class CliDataframesGet(lister.Lister):
|
||||
"""Get dataframes from the storage backend."""
|
||||
columns = [
|
||||
('begin', 'Begin'),
|
||||
('end', 'End'),
|
||||
('metric', 'Metric Type'),
|
||||
('unit', 'Unit'),
|
||||
('qty', 'Quantity'),
|
||||
('price', 'Price'),
|
||||
('groupby', 'Group By'),
|
||||
('metadata', 'Metadata'),
|
||||
]
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(CliDataframesGet, self).get_parser(prog_name)
|
||||
|
||||
def filter_(elem):
|
||||
if len(elem.split(':')) != 2:
|
||||
raise TypeError
|
||||
return str(elem)
|
||||
|
||||
parser.add_argument('--offset', type=int, default=0,
|
||||
help='Index of the first dataframe')
|
||||
parser.add_argument('--limit', type=int, default=100,
|
||||
help='Maximal number of dataframes')
|
||||
parser.add_argument('--filter', type=filter_, action='append',
|
||||
help="Optional filter, in 'key:value' format. Can "
|
||||
"be specified several times.")
|
||||
parser.add_argument('-b', '--begin', type=timeutils.parse_isotime,
|
||||
help="Start of the period to query, in iso8601 "
|
||||
"format. Example: 2019-05-01T00:00:00Z.")
|
||||
parser.add_argument('-e', '--end', type=timeutils.parse_isotime,
|
||||
help="End of the period to query, in iso8601 "
|
||||
"format. Example: 2019-06-01T00:00:00Z.")
|
||||
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
filters = dict(elem.split(':') for elem in (parsed_args.filter or []))
|
||||
|
||||
dataframes = utils.get_client_from_osc(self).dataframes.get_dataframes(
|
||||
offset=parsed_args.offset,
|
||||
limit=parsed_args.limit,
|
||||
begin=parsed_args.begin,
|
||||
end=parsed_args.end,
|
||||
filters=filters,
|
||||
).get('dataframes', [])
|
||||
|
||||
def format_(d):
|
||||
return ' '.join([
|
||||
'{}="{}"'.format(k, v) for k, v in (d or {}).items()])
|
||||
|
||||
values = []
|
||||
for df in dataframes:
|
||||
period = df['period']
|
||||
usage = df['usage']
|
||||
for metric_type, points in usage.items():
|
||||
for point in points:
|
||||
values.append([
|
||||
period['begin'],
|
||||
period['end'],
|
||||
metric_type,
|
||||
point['vol']['unit'],
|
||||
point['vol']['qty'],
|
||||
point['rating']['price'],
|
||||
format_(point.get('groupby', {})),
|
||||
format_(point.get('metadata', {})),
|
||||
])
|
||||
|
||||
return [col[1] for col in self.columns], values
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Support for the ``GET /v2/dataframes`` endpoint has been added
|
||||
to the client. A new ``dataframes get`` CLI command is also available.
|
|
@ -88,6 +88,7 @@ openstack.rating.v1 =
|
|||
rating_pyscript_delete = cloudkittyclient.v1.rating.pyscripts_cli:CliDeleteScript
|
||||
|
||||
openstack.rating.v2 =
|
||||
rating_dataframes_get = cloudkittyclient.v2.dataframes_cli:CliDataframesGet
|
||||
rating_dataframes_add = cloudkittyclient.v2.dataframes_cli:CliDataframesAdd
|
||||
|
||||
rating_scope_state_get = cloudkittyclient.v2.scope_cli:CliScopeStateGet
|
||||
|
@ -139,7 +140,6 @@ openstack.rating.v2 =
|
|||
rating_collector_state_get = cloudkittyclient.v1.collector_cli:CliCollectorGetState
|
||||
rating_collector_enable = cloudkittyclient.v1.collector_cli:CliCollectorEnable
|
||||
rating_collector_disable = cloudkittyclient.v1.collector_cli:CliCollectorDisable
|
||||
rating_dataframes_get = cloudkittyclient.v1.storage_cli:CliGetDataframes
|
||||
|
||||
rating_pyscript_create = cloudkittyclient.v1.rating.pyscripts_cli:CliCreateScript
|
||||
rating_pyscript_list = cloudkittyclient.v1.rating.pyscripts_cli:CliListScripts
|
||||
|
@ -205,6 +205,7 @@ cloudkittyclient_v1 =
|
|||
|
||||
cloudkittyclient_v2 =
|
||||
dataframes_add = cloudkittyclient.v2.dataframes_cli:CliDataframesAdd
|
||||
dataframes_get = cloudkittyclient.v2.dataframes_cli:CliDataframesGet
|
||||
|
||||
scope_state_get = cloudkittyclient.v2.scope_cli:CliScopeStateGet
|
||||
scope_state_reset = cloudkittyclient.v2.scope_cli:CliScopeStateReset
|
||||
|
@ -256,7 +257,6 @@ cloudkittyclient_v2 =
|
|||
collector_state_get = cloudkittyclient.v1.collector_cli:CliCollectorGetState
|
||||
collector_enable = cloudkittyclient.v1.collector_cli:CliCollectorEnable
|
||||
collector_disable = cloudkittyclient.v1.collector_cli:CliCollectorDisable
|
||||
dataframes_get = cloudkittyclient.v1.storage_cli:CliGetDataframes
|
||||
|
||||
pyscript_create = cloudkittyclient.v1.rating.pyscripts_cli:CliCreateScript
|
||||
pyscript_list = cloudkittyclient.v1.rating.pyscripts_cli:CliListScripts
|
||||
|
|
Loading…
Reference in New Issue