Added gabbi API tests
Added tests on all the core API. Change-Id: I6610ddbe5071ce1231c80319ab1b43c9cd626de4 Depends-On: I2231521708f163d80538fe2e7e5559d4c06cf0c3 Depends-On: Ib05d533eecd32159c1bc7a639db1a49df678f726 Depends-On: I3302617c266111ba1d705d04f1acf20b9348614d Depends-On: I0ab0f1b2a75d39b8d371c54a264856db69adc2fd
This commit is contained in:
parent
23458597ab
commit
04a9f0cd43
|
@ -2,3 +2,4 @@
|
||||||
test_command=${PYTHON:-python} -m subunit.run discover -t ./ ./cloudkitty/tests $LISTOPT $IDOPTION
|
test_command=${PYTHON:-python} -m subunit.run discover -t ./ ./cloudkitty/tests $LISTOPT $IDOPTION
|
||||||
test_id_option=--load-list $IDFILE
|
test_id_option=--load-list $IDFILE
|
||||||
test_list_option=--list
|
test_list_option=--list
|
||||||
|
group_regex=gabbi\.driver\.(test_[^_]+_[^_]+)
|
||||||
|
|
|
@ -48,12 +48,13 @@ auth_opts = [
|
||||||
api_opts = [
|
api_opts = [
|
||||||
cfg.StrOpt('host_ip',
|
cfg.StrOpt('host_ip',
|
||||||
default="0.0.0.0",
|
default="0.0.0.0",
|
||||||
help="Host serving the API."
|
help="Host serving the API."),
|
||||||
),
|
|
||||||
cfg.IntOpt('port',
|
cfg.IntOpt('port',
|
||||||
default=8888,
|
default=8888,
|
||||||
help="Host port serving the API."
|
help="Host port serving the API."),
|
||||||
),
|
cfg.BoolOpt('pecan_debug',
|
||||||
|
default=False,
|
||||||
|
help='Toggle Pecan Debug Middleware.'),
|
||||||
]
|
]
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
@ -87,7 +88,7 @@ def setup_app(pecan_config=None, extra_hooks=None):
|
||||||
app_conf.app.root,
|
app_conf.app.root,
|
||||||
static_root=app_conf.app.static_root,
|
static_root=app_conf.app.static_root,
|
||||||
template_path=app_conf.app.template_path,
|
template_path=app_conf.app.template_path,
|
||||||
debug=CONF.debug,
|
debug=CONF.api.pecan_debug,
|
||||||
force_canonical=getattr(app_conf.app, 'force_canonical', True),
|
force_canonical=getattr(app_conf.app, 'force_canonical', True),
|
||||||
hooks=app_hooks,
|
hooks=app_hooks,
|
||||||
guess_content_type_from_ext=False
|
guess_content_type_from_ext=False
|
||||||
|
|
|
@ -102,7 +102,7 @@ class ModulesController(rest.RestController, RatingModulesMixin):
|
||||||
with lock:
|
with lock:
|
||||||
module = self.extensions[module_id]
|
module = self.extensions[module_id]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pecan.abort(404, 'Module not found.')
|
pecan.abort(400, 'Module not found.')
|
||||||
infos = module.obj.module_info.copy()
|
infos = module.obj.module_info.copy()
|
||||||
infos['module_id'] = infos.pop('name')
|
infos['module_id'] = infos.pop('name')
|
||||||
return rating_models.CloudkittyModule(**infos)
|
return rating_models.CloudkittyModule(**infos)
|
||||||
|
@ -218,3 +218,4 @@ class RatingController(rest.RestController):
|
||||||
policy.enforce(pecan.request.context, 'rating:module_config', {})
|
policy.enforce(pecan.request.context, 'rating:module_config', {})
|
||||||
self.modules.reload_extensions()
|
self.modules.reload_extensions()
|
||||||
self.module_config.reload_extensions()
|
self.module_config.reload_extensions()
|
||||||
|
self.module_config.expose_modules()
|
||||||
|
|
|
@ -54,25 +54,28 @@ class DataFramesController(rest.RestController):
|
||||||
backend = pecan.request.storage_backend
|
backend = pecan.request.storage_backend
|
||||||
dataframes = []
|
dataframes = []
|
||||||
try:
|
try:
|
||||||
frames = backend.get_time_frame(begin_ts, end_ts,
|
frames = backend.get_time_frame(begin_ts,
|
||||||
|
end_ts,
|
||||||
tenant_id=tenant_id,
|
tenant_id=tenant_id,
|
||||||
res_type=resource_type)
|
res_type=resource_type)
|
||||||
for frame in frames:
|
for frame in frames:
|
||||||
for service, data_list in frame['usage'].items():
|
for service, data_list in frame['usage'].items():
|
||||||
|
frame_tenant = None
|
||||||
resources = []
|
resources = []
|
||||||
for data in data_list:
|
for data in data_list:
|
||||||
desc = data['desc'] if data['desc'] else {}
|
desc = data['desc'] if data['desc'] else {}
|
||||||
price = decimal.Decimal(data['rating']['price'])
|
price = decimal.Decimal(str(data['rating']['price']))
|
||||||
resource = storage_models.RatedResource(
|
resource = storage_models.RatedResource(
|
||||||
service=service,
|
service=service,
|
||||||
desc=desc,
|
desc=desc,
|
||||||
volume=data['vol']['qty'],
|
volume=data['vol']['qty'],
|
||||||
rating=price)
|
rating=price)
|
||||||
|
frame_tenant = data['tenant_id']
|
||||||
resources.append(resource)
|
resources.append(resource)
|
||||||
dataframe = storage_models.DataFrame(
|
dataframe = storage_models.DataFrame(
|
||||||
begin=ck_utils.iso2dt(frame['period']['begin']),
|
begin=ck_utils.iso2dt(frame['period']['begin']),
|
||||||
end=ck_utils.iso2dt(frame['period']['end']),
|
end=ck_utils.iso2dt(frame['period']['end']),
|
||||||
tenant_id=tenant_id, # FIXME
|
tenant_id=frame_tenant,
|
||||||
resources=resources)
|
resources=resources)
|
||||||
dataframes.append(dataframe)
|
dataframes.append(dataframe)
|
||||||
except ck_storage.NoTimeFrame:
|
except ck_storage.NoTimeFrame:
|
||||||
|
|
|
@ -60,7 +60,7 @@ class RatedDataFrame(Base, models.ModelBase):
|
||||||
|
|
||||||
# Volume informations
|
# Volume informations
|
||||||
vol_dict = {}
|
vol_dict = {}
|
||||||
vol_dict['qty'] = self.qty
|
vol_dict['qty'] = self.qty.normalize()
|
||||||
vol_dict['unit'] = self.unit
|
vol_dict['unit'] = self.unit
|
||||||
res_dict = {}
|
res_dict = {}
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,20 @@ from oslo_config import fixture as config_fixture
|
||||||
from oslotest import base
|
from oslotest import base
|
||||||
import testscenarios
|
import testscenarios
|
||||||
|
|
||||||
|
from cloudkitty import collector
|
||||||
from cloudkitty import db
|
from cloudkitty import db
|
||||||
from cloudkitty.db import api as ck_db_api
|
from cloudkitty.db import api as ck_db_api
|
||||||
from cloudkitty import rating
|
from cloudkitty import rating
|
||||||
|
|
||||||
|
|
||||||
|
class FakeCollectorModule(collector.BaseCollector):
|
||||||
|
collector_name = 'test_fake'
|
||||||
|
dependencies = tuple()
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(FakeCollectorModule, self).__init__([], period=3600)
|
||||||
|
|
||||||
|
|
||||||
class FakeRatingModule(rating.RatingProcessorBase):
|
class FakeRatingModule(rating.RatingProcessorBase):
|
||||||
module_name = 'fake'
|
module_name = 'fake'
|
||||||
description = 'fake rating module'
|
description = 'fake rating module'
|
||||||
|
|
|
@ -0,0 +1,311 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright 2015 Objectif Libre
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
# @author: Stéphane Albert
|
||||||
|
#
|
||||||
|
import abc
|
||||||
|
import decimal
|
||||||
|
import os
|
||||||
|
|
||||||
|
from gabbi import fixture
|
||||||
|
import mock
|
||||||
|
from oslo_config import cfg
|
||||||
|
from oslo_config import fixture as conf_fixture
|
||||||
|
from oslo_db.sqlalchemy import utils
|
||||||
|
import oslo_messaging as messaging
|
||||||
|
from oslo_messaging import conffixture
|
||||||
|
from oslo_policy import opts as policy_opts
|
||||||
|
import six
|
||||||
|
from stevedore import driver
|
||||||
|
from stevedore import extension
|
||||||
|
from wsme import types as wtypes
|
||||||
|
import wsmeext.pecan as wsme_pecan
|
||||||
|
|
||||||
|
from cloudkitty.api import app
|
||||||
|
from cloudkitty.common import rpc
|
||||||
|
from cloudkitty import db
|
||||||
|
from cloudkitty.db import api as ck_db_api
|
||||||
|
from cloudkitty import rating
|
||||||
|
from cloudkitty import storage
|
||||||
|
from cloudkitty.storage.sqlalchemy import models
|
||||||
|
from cloudkitty import tests
|
||||||
|
from cloudkitty import utils as ck_utils
|
||||||
|
|
||||||
|
INITIAL_TIMESTAMP = 1420070400
|
||||||
|
|
||||||
|
|
||||||
|
class UUIDFixture(fixture.GabbiFixture):
|
||||||
|
def start_fixture(self):
|
||||||
|
FAKE_UUID = '6c1b8a30-797f-4b7e-ad66-9879b79059fb'
|
||||||
|
patcher = mock.patch(
|
||||||
|
'oslo_utils.uuidutils.generate_uuid',
|
||||||
|
return_value=FAKE_UUID)
|
||||||
|
patcher.start()
|
||||||
|
self.patcher = patcher
|
||||||
|
|
||||||
|
def stop_fixture(self):
|
||||||
|
self.patcher.stop()
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class BaseExtensionFixture(fixture.GabbiFixture):
|
||||||
|
klass = None
|
||||||
|
namespace = None
|
||||||
|
stevedore_mgr = None
|
||||||
|
assert_args = {}
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def setup_fake_modules(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def start_fixture(self):
|
||||||
|
fake_extensions = self.setup_fake_modules()
|
||||||
|
self.mock = mock.patch(self.klass)
|
||||||
|
fake_mgr = self.stevedore_mgr.make_test_instance(
|
||||||
|
fake_extensions,
|
||||||
|
self.namespace)
|
||||||
|
self.patch = self.mock.start()
|
||||||
|
self.patch.return_value = fake_mgr
|
||||||
|
|
||||||
|
def stop_fixture(self):
|
||||||
|
self.patch.assert_called_with(
|
||||||
|
self.namespace,
|
||||||
|
**self.assert_args)
|
||||||
|
self.mock.stop()
|
||||||
|
|
||||||
|
|
||||||
|
class CollectorExtensionsFixture(BaseExtensionFixture):
|
||||||
|
klass = 'stevedore.driver.DriverManager'
|
||||||
|
namespace = 'cloudkitty.collector.backends'
|
||||||
|
stevedore_mgr = driver.DriverManager
|
||||||
|
assert_args = {
|
||||||
|
'invoke_kwds': {'period': 3600},
|
||||||
|
'invoke_on_load': True}
|
||||||
|
|
||||||
|
def setup_fake_modules(self):
|
||||||
|
def fake_metric(start,
|
||||||
|
end=None,
|
||||||
|
project_id=None,
|
||||||
|
q_filter=None):
|
||||||
|
return None
|
||||||
|
|
||||||
|
fake_module1 = tests.FakeCollectorModule()
|
||||||
|
fake_module1.collector_name = 'fake1'
|
||||||
|
fake_module1.get_compute = fake_metric
|
||||||
|
fake_module2 = tests.FakeCollectorModule()
|
||||||
|
fake_module2.collector_name = 'fake2'
|
||||||
|
fake_module2.get_volume = fake_metric
|
||||||
|
fake_module3 = tests.FakeCollectorModule()
|
||||||
|
fake_module3.collector_name = 'fake3'
|
||||||
|
fake_module3.get_compute = fake_metric
|
||||||
|
fake_extensions = [
|
||||||
|
extension.Extension(
|
||||||
|
'fake1',
|
||||||
|
'cloudkitty.tests.FakeCollectorModule1',
|
||||||
|
None,
|
||||||
|
fake_module1),
|
||||||
|
extension.Extension(
|
||||||
|
'fake2',
|
||||||
|
'cloudkitty.tests.FakeCollectorModule2',
|
||||||
|
None,
|
||||||
|
fake_module2),
|
||||||
|
extension.Extension(
|
||||||
|
'fake3',
|
||||||
|
'cloudkitty.tests.FakeCollectorModule3',
|
||||||
|
None,
|
||||||
|
fake_module3)]
|
||||||
|
return fake_extensions[0]
|
||||||
|
|
||||||
|
|
||||||
|
class RatingModulesFixture(BaseExtensionFixture):
|
||||||
|
klass = 'stevedore.extension.ExtensionManager'
|
||||||
|
namespace = 'cloudkitty.rating.processors'
|
||||||
|
stevedore_mgr = extension.ExtensionManager
|
||||||
|
assert_args = {
|
||||||
|
'invoke_on_load': True}
|
||||||
|
|
||||||
|
def setup_fake_modules(self):
|
||||||
|
class FakeConfigController(rating.RatingRestControllerBase):
|
||||||
|
_custom_actions = {
|
||||||
|
'test': ['GET']
|
||||||
|
}
|
||||||
|
|
||||||
|
@wsme_pecan.wsexpose(wtypes.text)
|
||||||
|
def get_test(self):
|
||||||
|
"""Return the list of every mapping type available.
|
||||||
|
|
||||||
|
"""
|
||||||
|
return 'OK'
|
||||||
|
|
||||||
|
fake_module1 = tests.FakeRatingModule()
|
||||||
|
fake_module1.module_name = 'fake1'
|
||||||
|
fake_module1.set_priority(3)
|
||||||
|
fake_module2 = tests.FakeRatingModule()
|
||||||
|
fake_module2.module_name = 'fake2'
|
||||||
|
fake_module2.config_controller = FakeConfigController
|
||||||
|
fake_module2.set_priority(1)
|
||||||
|
fake_module3 = tests.FakeRatingModule()
|
||||||
|
fake_module3.module_name = 'fake3'
|
||||||
|
fake_module3.set_priority(2)
|
||||||
|
fake_extensions = [
|
||||||
|
extension.Extension(
|
||||||
|
'fake1',
|
||||||
|
'cloudkitty.tests.FakeRatingModule1',
|
||||||
|
None,
|
||||||
|
fake_module1),
|
||||||
|
extension.Extension(
|
||||||
|
'fake2',
|
||||||
|
'cloudkitty.tests.FakeRatingModule2',
|
||||||
|
None,
|
||||||
|
fake_module2),
|
||||||
|
extension.Extension(
|
||||||
|
'fake3',
|
||||||
|
'cloudkitty.tests.FakeRatingModule3',
|
||||||
|
None,
|
||||||
|
fake_module3)]
|
||||||
|
return fake_extensions
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigFixture(fixture.GabbiFixture):
|
||||||
|
def start_fixture(self):
|
||||||
|
self.conf = None
|
||||||
|
conf = conf_fixture.Config().conf
|
||||||
|
policy_opts.set_defaults(conf)
|
||||||
|
msg_conf = conffixture.ConfFixture(conf)
|
||||||
|
msg_conf.transport_driver = 'fake'
|
||||||
|
conf.import_group('api', 'cloudkitty.api.app')
|
||||||
|
conf.set_override('auth_strategy', 'noauth')
|
||||||
|
conf.set_override('connection', 'sqlite:///', 'database')
|
||||||
|
conf.set_override('policy_file',
|
||||||
|
os.path.abspath('etc/cloudkitty/policy.json'),
|
||||||
|
group='oslo_policy')
|
||||||
|
conf.import_group('storage', 'cloudkitty.storage')
|
||||||
|
conf.set_override('backend', 'sqlalchemy', 'storage')
|
||||||
|
self.conf = conf
|
||||||
|
self.conn = ck_db_api.get_instance()
|
||||||
|
migration = self.conn.get_migration()
|
||||||
|
migration.upgrade('head')
|
||||||
|
|
||||||
|
def stop_fixture(self):
|
||||||
|
if self.conf:
|
||||||
|
self.conf.reset()
|
||||||
|
db.get_engine().dispose()
|
||||||
|
|
||||||
|
|
||||||
|
class BaseFakeRPC(fixture.GabbiFixture):
|
||||||
|
endpoint = None
|
||||||
|
|
||||||
|
def start_fixture(self):
|
||||||
|
rpc.init()
|
||||||
|
target = messaging.Target(topic='cloudkitty',
|
||||||
|
server=cfg.CONF.host,
|
||||||
|
version='1.0')
|
||||||
|
endpoints = [
|
||||||
|
self.endpoint()
|
||||||
|
]
|
||||||
|
self.server = rpc.get_server(target, endpoints)
|
||||||
|
self.server.start()
|
||||||
|
|
||||||
|
def stop_fixture(self):
|
||||||
|
self.server.stop()
|
||||||
|
|
||||||
|
|
||||||
|
class QuoteFakeRPC(BaseFakeRPC):
|
||||||
|
class FakeRPCEndpoint(object):
|
||||||
|
target = messaging.Target(namespace='rating',
|
||||||
|
version='1.0')
|
||||||
|
|
||||||
|
def quote(self, ctxt, res_data):
|
||||||
|
return str(1.0)
|
||||||
|
|
||||||
|
endpoint = FakeRPCEndpoint
|
||||||
|
|
||||||
|
|
||||||
|
class BaseStorageDataFixture(fixture.GabbiFixture):
|
||||||
|
def create_fake_data(self, begin, end):
|
||||||
|
data = [{
|
||||||
|
"period": {
|
||||||
|
"begin": begin,
|
||||||
|
"end": end},
|
||||||
|
"usage": {
|
||||||
|
"compute": [
|
||||||
|
{
|
||||||
|
"desc": {
|
||||||
|
"dummy": True,
|
||||||
|
"fake_meta": 1.0},
|
||||||
|
"vol": {
|
||||||
|
"qty": 1,
|
||||||
|
"unit": "nothing"},
|
||||||
|
"rating": {
|
||||||
|
"price": decimal.Decimal('1.337')}}]}}]
|
||||||
|
return data
|
||||||
|
|
||||||
|
def start_fixture(self):
|
||||||
|
self.storage = storage.get_storage()
|
||||||
|
self.storage.init()
|
||||||
|
self.initialize_data()
|
||||||
|
|
||||||
|
def stop_fixture(self):
|
||||||
|
model = models.RatedDataFrame
|
||||||
|
session = db.get_session()
|
||||||
|
q = utils.model_query(
|
||||||
|
model,
|
||||||
|
session)
|
||||||
|
q.delete()
|
||||||
|
|
||||||
|
|
||||||
|
class StorageDataFixture(BaseStorageDataFixture):
|
||||||
|
def initialize_data(self):
|
||||||
|
nodata_duration = (24 * 3 + 12) * 3600
|
||||||
|
tenant_list = ['8f82cc70-e50c-466e-8624-24bdea811375',
|
||||||
|
'7606a24a-b8ad-4ae0-be6c-3d7a41334a2e']
|
||||||
|
for tenant in tenant_list:
|
||||||
|
for i in range(INITIAL_TIMESTAMP,
|
||||||
|
INITIAL_TIMESTAMP + nodata_duration,
|
||||||
|
3600):
|
||||||
|
self.storage.nodata(i, i + 3600, tenant)
|
||||||
|
data_ts = INITIAL_TIMESTAMP + nodata_duration + 3600
|
||||||
|
data_duration = (24 * 2 + 8) * 3600
|
||||||
|
for i in range(data_ts,
|
||||||
|
data_ts + data_duration,
|
||||||
|
3600):
|
||||||
|
data = self.create_fake_data(i, i + 3600)
|
||||||
|
self.storage.append(data, tenant_list[0])
|
||||||
|
half_duration = int(data_duration / 2)
|
||||||
|
for i in range(data_ts,
|
||||||
|
data_ts + half_duration,
|
||||||
|
3600):
|
||||||
|
data = self.create_fake_data(i, i + 3600)
|
||||||
|
self.storage.append(data, tenant_list[1])
|
||||||
|
for i in range(data_ts + half_duration + 3600,
|
||||||
|
data_ts + data_duration,
|
||||||
|
3600):
|
||||||
|
self.storage.nodata(i, i + 3600, tenant_list[1])
|
||||||
|
|
||||||
|
|
||||||
|
class NowStorageDataFixture(BaseStorageDataFixture):
|
||||||
|
def initialize_data(self):
|
||||||
|
begin = ck_utils.get_month_start_timestamp()
|
||||||
|
for i in range(begin,
|
||||||
|
begin + 3600 * 12,
|
||||||
|
3600):
|
||||||
|
data = self.create_fake_data(i, i + 3600)
|
||||||
|
self.storage.append(data,
|
||||||
|
'3d9a1b33-482f-42fd-aef9-b575a3da9369')
|
||||||
|
|
||||||
|
|
||||||
|
def setup_app():
|
||||||
|
rpc.init()
|
||||||
|
return app.setup_app()
|
|
@ -0,0 +1,158 @@
|
||||||
|
fixtures:
|
||||||
|
- ConfigFixture
|
||||||
|
- RatingModulesFixture
|
||||||
|
- QuoteFakeRPC
|
||||||
|
|
||||||
|
tests:
|
||||||
|
- name: reload list of modules available
|
||||||
|
url: /v1/billing/reload_modules
|
||||||
|
status: 204
|
||||||
|
|
||||||
|
- name: list all modules available
|
||||||
|
url: /v1/billing/modules
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.modules.`len`: 3
|
||||||
|
$.modules[0].priority: 3
|
||||||
|
$.modules[0].module_id: "fake1"
|
||||||
|
$.modules[0].enabled: false
|
||||||
|
$.modules[0].description: "fake rating module"
|
||||||
|
$.modules[0].hot-config: false
|
||||||
|
$.modules[1].priority: 1
|
||||||
|
$.modules[1].module_id: "fake2"
|
||||||
|
$.modules[1].enabled: false
|
||||||
|
$.modules[1].description: "fake rating module"
|
||||||
|
$.modules[1].hot-config: false
|
||||||
|
$.modules[2].priority: 2
|
||||||
|
$.modules[2].module_id: "fake3"
|
||||||
|
$.modules[2].enabled: false
|
||||||
|
$.modules[2].description: "fake rating module"
|
||||||
|
$.modules[2].hot-config: false
|
||||||
|
|
||||||
|
- name: get information of one module
|
||||||
|
url: /v1/billing/modules/fake2
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.priority: 1
|
||||||
|
$.module_id: "fake2"
|
||||||
|
$.enabled: false
|
||||||
|
$.description: "fake rating module"
|
||||||
|
$.hot-config: false
|
||||||
|
|
||||||
|
- name: get information of a unknown module
|
||||||
|
url: /v1/billing/modules/fakb
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- "Module not found."
|
||||||
|
|
||||||
|
- name: change priority of a module
|
||||||
|
url: /v1/billing/modules/fake3
|
||||||
|
method: PUT
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
x-roles: admin
|
||||||
|
data:
|
||||||
|
module_id: "fake3"
|
||||||
|
priority: 5
|
||||||
|
status: 302
|
||||||
|
response_headers:
|
||||||
|
location: "$SCHEME://$NETLOC/v1/billing/modules/fake3"
|
||||||
|
|
||||||
|
- name: get information of the modified module (priority)
|
||||||
|
url: $LOCATION
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.priority: 5
|
||||||
|
$.module_id: "fake3"
|
||||||
|
$.enabled: false
|
||||||
|
$.description: "fake rating module"
|
||||||
|
$.hot-config: false
|
||||||
|
|
||||||
|
- name: change enabled status of a module
|
||||||
|
url: /v1/billing/modules/fake3
|
||||||
|
method: PUT
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
x-roles: admin
|
||||||
|
data:
|
||||||
|
module_id: "fake3"
|
||||||
|
enabled: true
|
||||||
|
status: 302
|
||||||
|
response_headers:
|
||||||
|
location: "$SCHEME://$NETLOC/v1/billing/modules/fake3"
|
||||||
|
|
||||||
|
- name: get information of the modified module (status)
|
||||||
|
url: $LOCATION
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.priority: 5
|
||||||
|
$.module_id: "fake3"
|
||||||
|
$.enabled: true
|
||||||
|
$.description: "fake rating module"
|
||||||
|
$.hot-config: false
|
||||||
|
|
||||||
|
- name: change status and priority of a module
|
||||||
|
url: /v1/billing/modules/fake3
|
||||||
|
method: PUT
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
x-roles: admin
|
||||||
|
data:
|
||||||
|
module_id: "fake3"
|
||||||
|
priority: 3
|
||||||
|
enabled: false
|
||||||
|
status: 302
|
||||||
|
response_headers:
|
||||||
|
location: "$SCHEME://$NETLOC/v1/billing/modules/fake3"
|
||||||
|
|
||||||
|
- name: get information of the modified module (both)
|
||||||
|
url: $LOCATION
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.priority: 3
|
||||||
|
$.module_id: "fake3"
|
||||||
|
$.enabled: false
|
||||||
|
$.description: "fake rating module"
|
||||||
|
$.hot-config: false
|
||||||
|
|
||||||
|
- name: get a quote for a resource description
|
||||||
|
url: /v1/billing/quote
|
||||||
|
method: POST
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
x-roles: admin
|
||||||
|
data:
|
||||||
|
resources:
|
||||||
|
- service: "compute"
|
||||||
|
volume: "1.0"
|
||||||
|
desc:
|
||||||
|
test: 1
|
||||||
|
status: 200
|
||||||
|
response_strings:
|
||||||
|
- "1.0"
|
||||||
|
|
||||||
|
- name: module without custom API should use notconfigurable controller (GET)
|
||||||
|
url: /v1/billing/module_config/fake1
|
||||||
|
status: 409
|
||||||
|
response_strings:
|
||||||
|
- "Module is not configurable"
|
||||||
|
|
||||||
|
- name: module without custom API should use notconfigurable controller (POST)
|
||||||
|
url: /v1/billing/module_config/fake1
|
||||||
|
method: POST
|
||||||
|
status: 409
|
||||||
|
response_strings:
|
||||||
|
- "Module is not configurable"
|
||||||
|
|
||||||
|
- name: module without custom API should use notconfigurable controller (PUT)
|
||||||
|
url: /v1/billing/module_config/fake1
|
||||||
|
method: PUT
|
||||||
|
status: 409
|
||||||
|
response_strings:
|
||||||
|
- "Module is not configurable"
|
||||||
|
|
||||||
|
- name: verify module exposes its custom API
|
||||||
|
url: /v1/billing/module_config/fake2/test
|
||||||
|
status: 200
|
||||||
|
response_strings:
|
||||||
|
- "OK"
|
|
@ -0,0 +1,138 @@
|
||||||
|
fixtures:
|
||||||
|
- ConfigFixture
|
||||||
|
|
||||||
|
tests:
|
||||||
|
|
||||||
|
# States
|
||||||
|
- name: check collector is disabled by default
|
||||||
|
url: /v1/collector/fake1/states
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.enabled: false
|
||||||
|
$.name: "fake1"
|
||||||
|
|
||||||
|
- name: enable collector
|
||||||
|
url: /v1/collector/fake1/states
|
||||||
|
method: PUT
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
x-roles: admin
|
||||||
|
data:
|
||||||
|
name: "fake1"
|
||||||
|
enabled: true
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.enabled: true
|
||||||
|
$.name: "fake1"
|
||||||
|
|
||||||
|
- name: check collector state isolation
|
||||||
|
url: /v1/collector/fake2/states
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.enabled: false
|
||||||
|
$.name: "fake2"
|
||||||
|
|
||||||
|
- name: disable collector
|
||||||
|
url: /v1/collector/fake1/states
|
||||||
|
method: PUT
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
x-roles: admin
|
||||||
|
data:
|
||||||
|
name: "fake1"
|
||||||
|
enabled: false
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.enabled: false
|
||||||
|
$.name: "fake1"
|
||||||
|
|
||||||
|
# Mappings
|
||||||
|
- name: get all mappings (empty)
|
||||||
|
url: /v1/collector/mappings
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.mappings: []
|
||||||
|
|
||||||
|
- name: try to get an unknown mapping
|
||||||
|
url: /v1/collector/mappings/notfound
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- "No mapping for service: notfound"
|
||||||
|
|
||||||
|
- name: try to delete an unknown mapping
|
||||||
|
url: /v1/collector/mappings/notfound
|
||||||
|
method: DELETE
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- "No mapping for service: notfound"
|
||||||
|
|
||||||
|
- name: create mapping
|
||||||
|
url: /v1/collector/mappings/fake1/metric1
|
||||||
|
method: POST
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
x-roles: admin
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.collector: "fake1"
|
||||||
|
$.service: "metric1"
|
||||||
|
|
||||||
|
- name: get all mappings
|
||||||
|
url: /v1/collector/mappings
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.mappings[0].collector: "fake1"
|
||||||
|
$.mappings[0].service: "metric1"
|
||||||
|
|
||||||
|
- name: create second mapping
|
||||||
|
url: /v1/collector/mappings/fake2/metric8
|
||||||
|
method: POST
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
x-roles: admin
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.collector: "fake2"
|
||||||
|
$.service: "metric8"
|
||||||
|
|
||||||
|
- name: get all mappings filtering on collector fake1
|
||||||
|
url: /v1/collector/mappings?collector=fake1
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.mappings[0].collector: "fake1"
|
||||||
|
$.mappings[0].service: "metric1"
|
||||||
|
|
||||||
|
- name: get all mappings filtering on collector fake2
|
||||||
|
url: /v1/collector/mappings?collector=fake2
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.mappings[0].collector: "fake2"
|
||||||
|
$.mappings[0].service: "metric8"
|
||||||
|
|
||||||
|
- name: get all mappings with no filtering
|
||||||
|
url: /v1/collector/mappings
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.mappings.`len`: 2
|
||||||
|
$.mappings[0].collector: "fake1"
|
||||||
|
$.mappings[0].service: "metric1"
|
||||||
|
$.mappings[1].collector: "fake2"
|
||||||
|
$.mappings[1].service: "metric8"
|
||||||
|
|
||||||
|
- name: get a mapping filtering on service metric8
|
||||||
|
url: /v1/collector/mappings/metric8
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.collector: "fake2"
|
||||||
|
$.service: "metric8"
|
||||||
|
|
||||||
|
- name: delete a mapping
|
||||||
|
url: /v1/collector/mappings/metric1
|
||||||
|
method: DELETE
|
||||||
|
status: 204
|
||||||
|
|
||||||
|
- name: check the mapping got deleted
|
||||||
|
url: /v1/collector/mappings/metric1
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- "No mapping for service: metric1"
|
|
@ -0,0 +1,158 @@
|
||||||
|
fixtures:
|
||||||
|
- ConfigFixture
|
||||||
|
- RatingModulesFixture
|
||||||
|
- QuoteFakeRPC
|
||||||
|
|
||||||
|
tests:
|
||||||
|
- name: reload list of modules available
|
||||||
|
url: /v1/rating/reload_modules
|
||||||
|
status: 204
|
||||||
|
|
||||||
|
- name: list all modules available
|
||||||
|
url: /v1/rating/modules
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.modules.`len`: 3
|
||||||
|
$.modules[0].priority: 3
|
||||||
|
$.modules[0].module_id: "fake1"
|
||||||
|
$.modules[0].enabled: false
|
||||||
|
$.modules[0].description: "fake rating module"
|
||||||
|
$.modules[0].hot-config: false
|
||||||
|
$.modules[1].priority: 1
|
||||||
|
$.modules[1].module_id: "fake2"
|
||||||
|
$.modules[1].enabled: false
|
||||||
|
$.modules[1].description: "fake rating module"
|
||||||
|
$.modules[1].hot-config: false
|
||||||
|
$.modules[2].priority: 2
|
||||||
|
$.modules[2].module_id: "fake3"
|
||||||
|
$.modules[2].enabled: false
|
||||||
|
$.modules[2].description: "fake rating module"
|
||||||
|
$.modules[2].hot-config: false
|
||||||
|
|
||||||
|
- name: get information of one module
|
||||||
|
url: /v1/rating/modules/fake2
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.priority: 1
|
||||||
|
$.module_id: "fake2"
|
||||||
|
$.enabled: false
|
||||||
|
$.description: "fake rating module"
|
||||||
|
$.hot-config: false
|
||||||
|
|
||||||
|
- name: get information of a unknown module
|
||||||
|
url: /v1/rating/modules/fakb
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- "Module not found."
|
||||||
|
|
||||||
|
- name: change priority of a module
|
||||||
|
url: /v1/rating/modules/fake3
|
||||||
|
method: PUT
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
x-roles: admin
|
||||||
|
data:
|
||||||
|
module_id: "fake3"
|
||||||
|
priority: 5
|
||||||
|
status: 302
|
||||||
|
response_headers:
|
||||||
|
location: "$SCHEME://$NETLOC/v1/rating/modules/fake3"
|
||||||
|
|
||||||
|
- name: get information of the modified module (priority)
|
||||||
|
url: $LOCATION
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.priority: 5
|
||||||
|
$.module_id: "fake3"
|
||||||
|
$.enabled: false
|
||||||
|
$.description: "fake rating module"
|
||||||
|
$.hot-config: false
|
||||||
|
|
||||||
|
- name: change enabled status of a module
|
||||||
|
url: /v1/rating/modules/fake3
|
||||||
|
method: PUT
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
x-roles: admin
|
||||||
|
data:
|
||||||
|
module_id: "fake3"
|
||||||
|
enabled: true
|
||||||
|
status: 302
|
||||||
|
response_headers:
|
||||||
|
location: "$SCHEME://$NETLOC/v1/rating/modules/fake3"
|
||||||
|
|
||||||
|
- name: get information of the modified module (status)
|
||||||
|
url: $LOCATION
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.priority: 5
|
||||||
|
$.module_id: "fake3"
|
||||||
|
$.enabled: true
|
||||||
|
$.description: "fake rating module"
|
||||||
|
$.hot-config: false
|
||||||
|
|
||||||
|
- name: change status and priority of a module
|
||||||
|
url: /v1/rating/modules/fake3
|
||||||
|
method: PUT
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
x-roles: admin
|
||||||
|
data:
|
||||||
|
module_id: "fake3"
|
||||||
|
priority: 3
|
||||||
|
enabled: false
|
||||||
|
status: 302
|
||||||
|
response_headers:
|
||||||
|
location: "$SCHEME://$NETLOC/v1/rating/modules/fake3"
|
||||||
|
|
||||||
|
- name: get information of the modified module (both)
|
||||||
|
url: $LOCATION
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.priority: 3
|
||||||
|
$.module_id: "fake3"
|
||||||
|
$.enabled: false
|
||||||
|
$.description: "fake rating module"
|
||||||
|
$.hot-config: false
|
||||||
|
|
||||||
|
- name: get a quote for a resource description
|
||||||
|
url: /v1/rating/quote
|
||||||
|
method: POST
|
||||||
|
request_headers:
|
||||||
|
content-type: application/json
|
||||||
|
x-roles: admin
|
||||||
|
data:
|
||||||
|
resources:
|
||||||
|
- service: "compute"
|
||||||
|
volume: "1.0"
|
||||||
|
desc:
|
||||||
|
test: 1
|
||||||
|
status: 200
|
||||||
|
response_strings:
|
||||||
|
- "1.0"
|
||||||
|
|
||||||
|
- name: module without custom API should use notconfigurable controller (GET)
|
||||||
|
url: /v1/rating/module_config/fake1
|
||||||
|
status: 409
|
||||||
|
response_strings:
|
||||||
|
- "Module is not configurable"
|
||||||
|
|
||||||
|
- name: module without custom API should use notconfigurable controller (POST)
|
||||||
|
url: /v1/rating/module_config/fake1
|
||||||
|
method: POST
|
||||||
|
status: 409
|
||||||
|
response_strings:
|
||||||
|
- "Module is not configurable"
|
||||||
|
|
||||||
|
- name: module without custom API should use notconfigurable controller (PUT)
|
||||||
|
url: /v1/rating/module_config/fake1
|
||||||
|
method: PUT
|
||||||
|
status: 409
|
||||||
|
response_strings:
|
||||||
|
- "Module is not configurable"
|
||||||
|
|
||||||
|
- name: verify module exposes its custom API
|
||||||
|
url: /v1/rating/module_config/fake2/test
|
||||||
|
status: 200
|
||||||
|
response_strings:
|
||||||
|
- "OK"
|
|
@ -0,0 +1,68 @@
|
||||||
|
fixtures:
|
||||||
|
- ConfigFixture
|
||||||
|
- StorageDataFixture
|
||||||
|
- NowStorageDataFixture
|
||||||
|
|
||||||
|
tests:
|
||||||
|
- name: get period with two tenants
|
||||||
|
url: /v1/report/tenants
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-01-01T00:00:00"
|
||||||
|
end: "2015-01-04T00:00:00"
|
||||||
|
status: 200
|
||||||
|
response_strings:
|
||||||
|
- "8f82cc70-e50c-466e-8624-24bdea811375"
|
||||||
|
- "7606a24a-b8ad-4ae0-be6c-3d7a41334a2e"
|
||||||
|
|
||||||
|
- name: by default give tenants for the current month
|
||||||
|
url: /v1/report/tenants
|
||||||
|
status: 200
|
||||||
|
response_strings:
|
||||||
|
- "3d9a1b33-482f-42fd-aef9-b575a3da9369"
|
||||||
|
|
||||||
|
- name: get period with no tenants
|
||||||
|
url: /v1/report/tenants
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-02-01T00:00:00"
|
||||||
|
end: "2015-02-02T00:00:00"
|
||||||
|
status: 200
|
||||||
|
response_strings:
|
||||||
|
- "[]"
|
||||||
|
|
||||||
|
- name: get total for a period
|
||||||
|
url: /v1/report/total
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-01-01T00:00:00"
|
||||||
|
end: "2015-02-04T00:00:00"
|
||||||
|
status: 200
|
||||||
|
response_strings:
|
||||||
|
- "110.971"
|
||||||
|
|
||||||
|
- name: get total for a period filtering on first tenant
|
||||||
|
url: /v1/report/total
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-01-01T00:00:00"
|
||||||
|
end: "2015-02-04T00:00:00"
|
||||||
|
tenant_id: "8f82cc70-e50c-466e-8624-24bdea811375"
|
||||||
|
status: 200
|
||||||
|
response_strings:
|
||||||
|
- "73.535"
|
||||||
|
|
||||||
|
- name: get total for a period filtering on second tenant
|
||||||
|
url: /v1/report/total
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-01-01T00:00:00"
|
||||||
|
end: "2015-02-04T00:00:00"
|
||||||
|
tenant_id: "7606a24a-b8ad-4ae0-be6c-3d7a41334a2e"
|
||||||
|
status: 200
|
||||||
|
response_strings:
|
||||||
|
- "37.436"
|
||||||
|
|
||||||
|
- name: get total for a period with no data
|
||||||
|
url: /v1/report/total
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-02-01T00:00:00"
|
||||||
|
end: "2015-02-02T00:00:00"
|
||||||
|
status: 200
|
||||||
|
response_strings:
|
||||||
|
- "0"
|
|
@ -0,0 +1,135 @@
|
||||||
|
fixtures:
|
||||||
|
- ConfigFixture
|
||||||
|
- StorageDataFixture
|
||||||
|
|
||||||
|
tests:
|
||||||
|
- name: fetch period with no data
|
||||||
|
url: /v1/storage/dataframes
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-01-01T00:00:00"
|
||||||
|
end: "2015-01-04T00:00:00"
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.dataframes.`len`: 0
|
||||||
|
|
||||||
|
- name: fetch period with no data filtering on tenant_id
|
||||||
|
url: /v1/storage/dataframes
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-01-01T00:00:00"
|
||||||
|
end: "2015-01-04T00:00:00"
|
||||||
|
tenant_id: "8f82cc70-e50c-466e-8624-24bdea811375"
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.dataframes.`len`: 0
|
||||||
|
|
||||||
|
- name: check begin is mandatory for dataframes
|
||||||
|
url: /v1/storage/dataframes
|
||||||
|
query_parameters:
|
||||||
|
end: "2015-01-04T00:00:00"
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- "Missing argument: \\\"begin\\\""
|
||||||
|
|
||||||
|
- name: check end is mandatory for dataframes
|
||||||
|
url: /v1/storage/dataframes
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-01-04T00:00:00"
|
||||||
|
status: 400
|
||||||
|
response_strings:
|
||||||
|
- "Missing argument: \\\"end\\\""
|
||||||
|
|
||||||
|
- name: fetch data for the first tenant
|
||||||
|
url: /v1/storage/dataframes
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-01-04T13:00:00"
|
||||||
|
end: "2015-01-04T14:00:00"
|
||||||
|
tenant_id: "8f82cc70-e50c-466e-8624-24bdea811375"
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.dataframes.`len`: 1
|
||||||
|
$.dataframes[0].tenant_id: "8f82cc70-e50c-466e-8624-24bdea811375"
|
||||||
|
$.dataframes[0].begin: "2015-01-04T13:00:00"
|
||||||
|
$.dataframes[0].end: "2015-01-04T14:00:00"
|
||||||
|
$.dataframes[0].resources.`len`: 1
|
||||||
|
$.dataframes[0].resources[0].volume: "1"
|
||||||
|
$.dataframes[0].resources[0].rating: "1.337"
|
||||||
|
$.dataframes[0].resources[0].service: "compute"
|
||||||
|
$.dataframes[0].resources[0].desc.dummy: true
|
||||||
|
$.dataframes[0].resources[0].desc.fake_meta: 1.0
|
||||||
|
|
||||||
|
- name: fetch data for the second tenant
|
||||||
|
url: /v1/storage/dataframes
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-01-04T13:00:00"
|
||||||
|
end: "2015-01-04T14:00:00"
|
||||||
|
tenant_id: "7606a24a-b8ad-4ae0-be6c-3d7a41334a2e"
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.dataframes.`len`: 1
|
||||||
|
$.dataframes[0].tenant_id: "7606a24a-b8ad-4ae0-be6c-3d7a41334a2e"
|
||||||
|
$.dataframes[0].begin: "2015-01-04T13:00:00"
|
||||||
|
$.dataframes[0].end: "2015-01-04T14:00:00"
|
||||||
|
$.dataframes[0].resources.`len`: 1
|
||||||
|
$.dataframes[0].resources[0].volume: "1"
|
||||||
|
$.dataframes[0].resources[0].rating: "1.337"
|
||||||
|
$.dataframes[0].resources[0].service: "compute"
|
||||||
|
$.dataframes[0].resources[0].desc.dummy: true
|
||||||
|
$.dataframes[0].resources[0].desc.fake_meta: 1.0
|
||||||
|
|
||||||
|
- name: fetch data for multiple tenants
|
||||||
|
url: /v1/storage/dataframes
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-01-04T13:00:00"
|
||||||
|
end: "2015-01-04T14:00:00"
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.dataframes.`len`: 2
|
||||||
|
$.dataframes[0].tenant_id: "8f82cc70-e50c-466e-8624-24bdea811375"
|
||||||
|
$.dataframes[0].begin: "2015-01-04T13:00:00"
|
||||||
|
$.dataframes[0].end: "2015-01-04T14:00:00"
|
||||||
|
$.dataframes[0].resources.`len`: 1
|
||||||
|
$.dataframes[0].resources[0].volume: "1"
|
||||||
|
$.dataframes[0].resources[0].rating: "1.337"
|
||||||
|
$.dataframes[0].resources[0].service: "compute"
|
||||||
|
$.dataframes[0].resources[0].desc.dummy: true
|
||||||
|
$.dataframes[0].resources[0].desc.fake_meta: 1.0
|
||||||
|
$.dataframes[1].tenant_id: "7606a24a-b8ad-4ae0-be6c-3d7a41334a2e"
|
||||||
|
$.dataframes[1].begin: "2015-01-04T13:00:00"
|
||||||
|
$.dataframes[1].end: "2015-01-04T14:00:00"
|
||||||
|
$.dataframes[1].resources.`len`: 1
|
||||||
|
$.dataframes[1].resources[0].volume: "1"
|
||||||
|
$.dataframes[1].resources[0].rating: "1.337"
|
||||||
|
$.dataframes[1].resources[0].service: "compute"
|
||||||
|
$.dataframes[1].resources[0].desc.dummy: true
|
||||||
|
$.dataframes[1].resources[0].desc.fake_meta: 1.0
|
||||||
|
|
||||||
|
- name: fetch data filtering on service and tenant
|
||||||
|
url: /v1/storage/dataframes
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-01-04T13:00:00"
|
||||||
|
end: "2015-01-04T14:00:00"
|
||||||
|
resource_type: "compute"
|
||||||
|
tenant_id: "7606a24a-b8ad-4ae0-be6c-3d7a41334a2e"
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.dataframes.`len`: 1
|
||||||
|
$.dataframes[0].tenant_id: "7606a24a-b8ad-4ae0-be6c-3d7a41334a2e"
|
||||||
|
$.dataframes[0].begin: "2015-01-04T13:00:00"
|
||||||
|
$.dataframes[0].end: "2015-01-04T14:00:00"
|
||||||
|
$.dataframes[0].resources.`len`: 1
|
||||||
|
$.dataframes[0].resources[0].volume: "1"
|
||||||
|
$.dataframes[0].resources[0].rating: "1.337"
|
||||||
|
$.dataframes[0].resources[0].service: "compute"
|
||||||
|
$.dataframes[0].resources[0].desc.dummy: true
|
||||||
|
$.dataframes[0].resources[0].desc.fake_meta: 1.0
|
||||||
|
|
||||||
|
- name: fetch data filtering on service with no data and tenant
|
||||||
|
url: /v1/storage/dataframes
|
||||||
|
query_parameters:
|
||||||
|
begin: "2015-01-04T13:00:00"
|
||||||
|
end: "2015-01-04T14:00:00"
|
||||||
|
resource_type: "image"
|
||||||
|
tenant_id: "7606a24a-b8ad-4ae0-be6c-3d7a41334a2e"
|
||||||
|
status: 200
|
||||||
|
response_json_paths:
|
||||||
|
$.dataframes.`len`: 0
|
|
@ -0,0 +1,33 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright 2015 Objectif Libre
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
# @author: Stéphane Albert
|
||||||
|
#
|
||||||
|
import os
|
||||||
|
|
||||||
|
from gabbi import driver
|
||||||
|
|
||||||
|
from cloudkitty.tests.gabbi import fixtures
|
||||||
|
|
||||||
|
TESTS_DIR = 'gabbits'
|
||||||
|
|
||||||
|
|
||||||
|
def load_tests(loader, tests, pattern):
|
||||||
|
test_dir = os.path.join(os.path.dirname(__file__), TESTS_DIR)
|
||||||
|
return driver.build_tests(test_dir,
|
||||||
|
loader,
|
||||||
|
host=None,
|
||||||
|
intercept=fixtures.setup_app,
|
||||||
|
fixture_module=fixtures)
|
|
@ -26,6 +26,7 @@ import datetime
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from oslo_utils import timeutils
|
from oslo_utils import timeutils
|
||||||
|
from six import moves
|
||||||
from stevedore import extension
|
from stevedore import extension
|
||||||
|
|
||||||
|
|
||||||
|
@ -128,8 +129,20 @@ def get_next_month_timestamp(dt=None):
|
||||||
|
|
||||||
|
|
||||||
def refresh_stevedore(namespace=None):
|
def refresh_stevedore(namespace=None):
|
||||||
# Trigger reload of entry points
|
"""Trigger reload of entry points.
|
||||||
reload(sys.modules['pkg_resources'])
|
|
||||||
|
Useful to have dynamic loading/unloading of stevedore modules.
|
||||||
|
"""
|
||||||
|
# NOTE(sheeprine): pkg_resources doesn't support reload on python3 due to
|
||||||
|
# defining basestring which is still there on reload hence executing
|
||||||
|
# python2 related code.
|
||||||
|
try:
|
||||||
|
del sys.modules['pkg_resources'].basestring
|
||||||
|
except AttributeError:
|
||||||
|
# python2, do nothing
|
||||||
|
pass
|
||||||
|
# Force working_set reload
|
||||||
|
moves.reload_module(sys.modules['pkg_resources'])
|
||||||
# Clear stevedore cache
|
# Clear stevedore cache
|
||||||
cache = extension.ExtensionManager.ENTRY_POINT_CACHE
|
cache = extension.ExtensionManager.ENTRY_POINT_CACHE
|
||||||
if namespace:
|
if namespace:
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
output_file = etc/cloudkitty/cloudkitty.conf.sample
|
output_file = etc/cloudkitty/cloudkitty.conf.sample
|
||||||
namespace = cloudkitty.common.config
|
namespace = cloudkitty.common.config
|
||||||
namespace = oslo.messaging
|
namespace = oslo.concurrency
|
||||||
namespace = oslo.db
|
namespace = oslo.db
|
||||||
|
namespace = oslo.log
|
||||||
|
namespace = oslo.messaging
|
||||||
|
namespace = oslo.policy
|
||||||
namespace = keystonemiddleware.auth_token
|
namespace = keystonemiddleware.auth_token
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
hacking<0.10,>=0.9.2
|
hacking<0.10,>=0.9.2
|
||||||
coverage>=3.6
|
coverage>=3.6
|
||||||
discover
|
discover
|
||||||
|
gabbi>=0.12.0 # Apache-2.0
|
||||||
testscenarios>=0.4
|
testscenarios>=0.4
|
||||||
testrepository>=0.0.18
|
testrepository>=0.0.18
|
||||||
mock>=1.2
|
mock>=1.2
|
||||||
|
|
Loading…
Reference in New Issue