Merge "Allow to specify CLI arguments"
This commit is contained in:
commit
65ff274f9f
|
@ -3,13 +3,13 @@
|
|||
doc/build/*
|
||||
dist
|
||||
build
|
||||
cover
|
||||
.coverage
|
||||
cover/
|
||||
.coverage.*
|
||||
*.egg
|
||||
*.egg-info
|
||||
.eggs/
|
||||
.testrepository
|
||||
.tox
|
||||
.testrepository/
|
||||
.tox/
|
||||
ChangeLog
|
||||
MANIFEST
|
||||
AUTHORS
|
||||
|
|
|
@ -30,7 +30,7 @@ def get_wsgi_app():
|
|||
|
||||
return deploy.loadapp(
|
||||
'config:%s/log-api-paste.ini' % config_dir,
|
||||
relative_to='../../',
|
||||
relative_to='./',
|
||||
name='main'
|
||||
)
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import sys
|
||||
|
||||
from oslo_log import log
|
||||
|
||||
from monasca_log_api import conf
|
||||
|
@ -21,9 +23,17 @@ CONF = conf.CONF
|
|||
LOG = log.getLogger(__name__)
|
||||
|
||||
_CONF_LOADED = False
|
||||
_GUNICORN_MARKER = 'gunicorn'
|
||||
|
||||
|
||||
def parse_args():
|
||||
def _is_running_under_gunicorn():
|
||||
"""Evaluates if api runs under gunicorn"""
|
||||
content = filter(lambda x: x != sys.executable and _GUNICORN_MARKER in x,
|
||||
sys.argv or [])
|
||||
return len(list(content) if not isinstance(content, list) else content) > 0
|
||||
|
||||
|
||||
def parse_args(argv=None):
|
||||
global _CONF_LOADED
|
||||
if _CONF_LOADED:
|
||||
LOG.debug('Configuration has been already loaded')
|
||||
|
@ -32,11 +42,10 @@ def parse_args():
|
|||
log.set_defaults()
|
||||
log.register_options(CONF)
|
||||
|
||||
CONF(args=[],
|
||||
# NOTE(trebskit) this disables any oslo.cfg CLI
|
||||
# opts as gunicorn has some trouble with them
|
||||
# i.e. gunicorn's argparse clashes with the one
|
||||
# defined inside oslo.cfg
|
||||
argv = (argv if argv is not None else sys.argv[1:])
|
||||
args = ([] if _is_running_under_gunicorn() else argv or [])
|
||||
|
||||
CONF(args=args,
|
||||
prog='log-api',
|
||||
project='monasca',
|
||||
version=version.version_str,
|
||||
|
|
|
@ -20,23 +20,16 @@ import string
|
|||
|
||||
import falcon
|
||||
from falcon import testing
|
||||
import fixtures
|
||||
import mock
|
||||
from oslo_config import fixture as oo_cfg
|
||||
from oslo_context import fixture as oo_ctx
|
||||
from oslotest import base as os_test
|
||||
from oslotest import base as oslotest_base
|
||||
import six
|
||||
|
||||
from monasca_log_api.api.core import request
|
||||
from monasca_log_api import conf
|
||||
|
||||
|
||||
def mock_config(test):
|
||||
conf.register_opts()
|
||||
return test.useFixture(oo_cfg.Config(conf=conf.CONF))
|
||||
|
||||
|
||||
def mock_context(test):
|
||||
return test.useFixture(oo_ctx.ClearRequestContext())
|
||||
from monasca_log_api import config
|
||||
|
||||
|
||||
class MockedAPI(falcon.API):
|
||||
|
@ -125,19 +118,59 @@ UNICODE_MESSAGES = [
|
|||
]
|
||||
|
||||
|
||||
class DisableStatsdMixin(object):
|
||||
class DisableStatsdFixture(fixtures.Fixture):
|
||||
|
||||
def setUp(self):
|
||||
super(DisableStatsdMixin, self).setUp()
|
||||
self.statsd_patch = mock.patch('monascastatsd.Connection')
|
||||
self.statsd_check = self.statsd_patch.start()
|
||||
super(DisableStatsdFixture, self).setUp()
|
||||
statsd_patch = mock.patch('monascastatsd.Connection')
|
||||
statsd_patch.start()
|
||||
self.addCleanup(statsd_patch.stop)
|
||||
|
||||
|
||||
class BaseTestCase(DisableStatsdMixin, os_test.BaseTestCase):
|
||||
pass
|
||||
class ConfigFixture(oo_cfg.Config):
|
||||
"""Mocks configuration"""
|
||||
|
||||
def __init__(self):
|
||||
super(ConfigFixture, self).__init__(config.CONF)
|
||||
|
||||
def setUp(self):
|
||||
super(ConfigFixture, self).setUp()
|
||||
self.addCleanup(self._clean_config_loaded_flag)
|
||||
conf.register_opts()
|
||||
self._set_defaults()
|
||||
config.parse_args(argv=[]) # prevent oslo from parsing test args
|
||||
|
||||
@staticmethod
|
||||
def _clean_config_loaded_flag():
|
||||
config._CONF_LOADED = False
|
||||
|
||||
def _set_defaults(self):
|
||||
self.conf.set_default('kafka_url', '127.0.0.1', 'kafka_healthcheck')
|
||||
self.conf.set_default('kafka_url', '127.0.0.1', 'log_publisher')
|
||||
|
||||
|
||||
class BaseTestCase(oslotest_base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(BaseTestCase, self).setUp()
|
||||
self.useFixture(ConfigFixture())
|
||||
self.useFixture(DisableStatsdFixture())
|
||||
self.useFixture(oo_ctx.ClearRequestContext())
|
||||
|
||||
@staticmethod
|
||||
def conf_override(**kw):
|
||||
"""Override flag variables for a test."""
|
||||
group = kw.pop('group', None)
|
||||
for k, v in kw.items():
|
||||
config.CONF.set_override(k, v, group)
|
||||
|
||||
@staticmethod
|
||||
def conf_default(**kw):
|
||||
"""Override flag variables for a test."""
|
||||
group = kw.pop('group', None)
|
||||
for k, v in kw.items():
|
||||
config.CONF.set_default(k, v, group)
|
||||
|
||||
|
||||
class BaseApiTestCase(BaseTestCase, testing.TestBase):
|
||||
api_class = MockedAPI
|
||||
|
||||
def before(self):
|
||||
self.conf = mock_config(self)
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
# Copyright 2017 FUJITSU LIMITED
|
||||
#
|
||||
# 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.
|
||||
|
||||
import mock
|
||||
|
||||
from monasca_log_api import config
|
||||
from monasca_log_api.tests import base
|
||||
|
||||
|
||||
class TestConfig(base.BaseTestCase):
|
||||
|
||||
@mock.patch('monasca_log_api.config.sys')
|
||||
def test_should_return_true_if_runs_under_gunicorn(self, sys_patch):
|
||||
sys_patch.argv = [
|
||||
'/bin/gunicorn',
|
||||
'--capture-output',
|
||||
'--paste',
|
||||
'etc/monasca/log-api-paste.ini',
|
||||
'--workers',
|
||||
'1'
|
||||
]
|
||||
sys_patch.executable = '/bin/python'
|
||||
self.assertTrue(config._is_running_under_gunicorn())
|
||||
|
||||
@mock.patch('monasca_log_api.config.sys')
|
||||
def test_should_return_false_if_runs_without_gunicorn(self, sys_patch):
|
||||
sys_patch.argv = ['/bin/monasca-log-api']
|
||||
sys_patch.executable = '/bin/python'
|
||||
self.assertFalse(config._is_running_under_gunicorn())
|
|
@ -24,8 +24,8 @@ ENDPOINT = '/healthcheck'
|
|||
|
||||
|
||||
class TestApiHealthChecks(base.BaseApiTestCase):
|
||||
|
||||
def before(self):
|
||||
super(TestApiHealthChecks, self).before()
|
||||
self.resource = healthchecks.HealthChecks()
|
||||
self.api.add_route(
|
||||
ENDPOINT,
|
||||
|
|
|
@ -29,14 +29,9 @@ class KafkaCheckLogicTest(base.BaseTestCase):
|
|||
'kafka_topics': mocked_topics
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(KafkaCheckLogicTest, self).__init__(*args, **kwargs)
|
||||
self._conf = None
|
||||
|
||||
def setUp(self):
|
||||
super(KafkaCheckLogicTest, self).setUp()
|
||||
self._conf = base.mock_config(self)
|
||||
self._conf.config(group='kafka_healthcheck', **self.mock_config)
|
||||
self.conf_default(group='kafka_healthcheck', **self.mock_config)
|
||||
|
||||
@mock.patch('monasca_log_api.healthcheck.kafka_check.client.KafkaClient')
|
||||
def test_should_fail_kafka_unavailable(self, kafka_client):
|
||||
|
|
|
@ -20,6 +20,7 @@ import ujson
|
|||
import unittest
|
||||
|
||||
import mock
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log
|
||||
import six
|
||||
|
||||
|
@ -33,10 +34,6 @@ EPOCH_START = datetime.datetime(1970, 1, 1)
|
|||
|
||||
class TestSendMessage(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.conf = base.mock_config(self)
|
||||
return super(TestSendMessage, self).setUp()
|
||||
|
||||
@mock.patch('monasca_log_api.reference.common.log_publisher.producer'
|
||||
'.KafkaProducer')
|
||||
def test_should_not_send_empty_message(self, _):
|
||||
|
@ -133,16 +130,16 @@ class TestSendMessage(base.BaseTestCase):
|
|||
instance.send_message(msg)
|
||||
|
||||
instance._kafka_publisher.publish.assert_called_once_with(
|
||||
self.conf.conf.log_publisher.topics[0],
|
||||
cfg.CONF.log_publisher.topics[0],
|
||||
[ujson.dumps(msg, ensure_ascii=False).encode('utf-8')])
|
||||
|
||||
@mock.patch('monasca_log_api.reference.common.log_publisher.producer'
|
||||
'.KafkaProducer')
|
||||
def test_should_send_message_multiple_topics(self, _):
|
||||
topics = ['logs', 'analyzer', 'tester']
|
||||
self.conf.config(topics=topics,
|
||||
max_message_size=5000,
|
||||
group='log_publisher')
|
||||
self.conf_override(topics=topics,
|
||||
max_message_size=5000,
|
||||
group='log_publisher')
|
||||
|
||||
instance = log_publisher.LogPublisher()
|
||||
instance._kafka_publisher = mock.Mock()
|
||||
|
@ -210,7 +207,7 @@ class TestSendMessage(base.BaseTestCase):
|
|||
expected_message = expected_message.encode('utf-8')
|
||||
|
||||
instance._kafka_publisher.publish.assert_called_with(
|
||||
self.conf.conf.log_publisher.topics[0],
|
||||
cfg.CONF.log_publisher.topics[0],
|
||||
[expected_message]
|
||||
)
|
||||
except Exception:
|
||||
|
@ -228,14 +225,6 @@ class TestTruncation(base.BaseTestCase):
|
|||
}
|
||||
}), 'utf8')) - 2
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestTruncation, self).__init__(*args, **kwargs)
|
||||
self._conf = None
|
||||
|
||||
def setUp(self):
|
||||
super(TestTruncation, self).setUp()
|
||||
self._conf = base.mock_config(self)
|
||||
|
||||
def test_should_not_truncate_message_if_size_is_smaller(self, _):
|
||||
diff_size = random.randint(1, 100)
|
||||
self._run_truncate_test(log_size_factor=-diff_size,
|
||||
|
@ -269,7 +258,7 @@ class TestTruncation(base.BaseTestCase):
|
|||
|
||||
expected_log_message_size = log_size - truncate_by
|
||||
|
||||
self._conf.config(
|
||||
self.conf_override(
|
||||
group='log_publisher',
|
||||
max_message_size=max_message_size
|
||||
)
|
||||
|
|
|
@ -196,7 +196,7 @@ class TestApiLogs(base.BaseApiTestCase):
|
|||
|
||||
max_log_size = 1000
|
||||
content_length = max_log_size - 100
|
||||
self.conf.config(max_log_size=max_log_size, group='service')
|
||||
self.conf_override(max_log_size=max_log_size, group='service')
|
||||
|
||||
self.simulate_request(
|
||||
'/log/single',
|
||||
|
@ -217,7 +217,7 @@ class TestApiLogs(base.BaseApiTestCase):
|
|||
|
||||
max_log_size = 1000
|
||||
content_length = max_log_size + 100
|
||||
self.conf.config(max_log_size=max_log_size, group='service')
|
||||
self.conf_override(max_log_size=max_log_size, group='service')
|
||||
|
||||
self.simulate_request(
|
||||
'/log/single',
|
||||
|
@ -238,7 +238,7 @@ class TestApiLogs(base.BaseApiTestCase):
|
|||
|
||||
max_log_size = 1000
|
||||
content_length = max_log_size
|
||||
self.conf.config(max_log_size=max_log_size, group='service')
|
||||
self.conf_override(max_log_size=max_log_size, group='service')
|
||||
|
||||
self.simulate_request(
|
||||
'/log/single',
|
||||
|
|
|
@ -203,9 +203,6 @@ class TestApiLogsMonitoring(base.BaseApiTestCase):
|
|||
|
||||
class TestApiLogs(base.BaseApiTestCase):
|
||||
|
||||
def before(self):
|
||||
self.conf = base.mock_config(self)
|
||||
|
||||
@mock.patch('monasca_log_api.reference.v3.common.bulk_processor.'
|
||||
'BulkProcessor')
|
||||
def test_should_pass_cross_tenant_id(self, bulk_processor):
|
||||
|
|
|
@ -20,10 +20,6 @@ from monasca_log_api.tests import base
|
|||
|
||||
class TestMonitoring(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestMonitoring, self).setUp()
|
||||
base.mock_config(self)
|
||||
|
||||
@mock.patch('monasca_log_api.monitoring.client.monascastatsd')
|
||||
def test_should_use_default_dimensions_if_none_specified(self,
|
||||
monascastatsd):
|
||||
|
|
|
@ -22,11 +22,6 @@ from monasca_log_api.tests import base
|
|||
|
||||
class TestRequest(base.BaseTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRequest, self).setUp()
|
||||
base.mock_config(self)
|
||||
base.mock_context(self)
|
||||
|
||||
def test_use_context_from_request(self):
|
||||
req = request.Request(
|
||||
testing.create_environ(
|
||||
|
|
|
@ -30,13 +30,8 @@ class IsDelegate(base.BaseTestCase):
|
|||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(IsDelegate, self).__init__(*args, **kwargs)
|
||||
self._conf = None
|
||||
self._roles = ['admin']
|
||||
|
||||
def setUp(self):
|
||||
super(IsDelegate, self).setUp()
|
||||
self._conf = base.mock_config(self)
|
||||
|
||||
def test_is_delegate_ok_role(self):
|
||||
self.assertTrue(validation.validate_is_delegate(self._roles))
|
||||
|
||||
|
@ -277,9 +272,6 @@ class ContentTypeValidations(base.BaseTestCase):
|
|||
|
||||
|
||||
class PayloadSizeValidations(base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(PayloadSizeValidations, self).setUp()
|
||||
self.conf = base.mock_config(self)
|
||||
|
||||
def test_should_fail_missing_header(self):
|
||||
content_length = None
|
||||
|
@ -294,8 +286,8 @@ class PayloadSizeValidations(base.BaseTestCase):
|
|||
def test_should_pass_limit_not_exceeded(self):
|
||||
content_length = 120
|
||||
max_log_size = 240
|
||||
self.conf.config(max_log_size=max_log_size,
|
||||
group='service')
|
||||
self.conf_override(max_log_size=max_log_size,
|
||||
group='service')
|
||||
|
||||
req = mock.Mock()
|
||||
req.content_length = content_length
|
||||
|
@ -305,8 +297,8 @@ class PayloadSizeValidations(base.BaseTestCase):
|
|||
def test_should_fail_limit_exceeded(self):
|
||||
content_length = 120
|
||||
max_log_size = 60
|
||||
self.conf.config(max_log_size=max_log_size,
|
||||
group='service')
|
||||
self.conf_override(max_log_size=max_log_size,
|
||||
group='service')
|
||||
|
||||
req = mock.Mock()
|
||||
req.content_length = content_length
|
||||
|
@ -320,8 +312,8 @@ class PayloadSizeValidations(base.BaseTestCase):
|
|||
def test_should_fail_limit_equal(self):
|
||||
content_length = 120
|
||||
max_log_size = 120
|
||||
self.conf.config(max_log_size=max_log_size,
|
||||
group='service')
|
||||
self.conf_override(max_log_size=max_log_size,
|
||||
group='service')
|
||||
|
||||
req = mock.Mock()
|
||||
req.content_length = content_length
|
||||
|
|
|
@ -24,12 +24,8 @@ def _get_versioned_url(version_id):
|
|||
|
||||
|
||||
class TestApiVersions(base.BaseApiTestCase):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.versions = None
|
||||
super(TestApiVersions, self).__init__(*args, **kwargs)
|
||||
|
||||
def before(self):
|
||||
super(TestApiVersions, self).before()
|
||||
self.versions = versions.Versions()
|
||||
self.api.add_route("/version/", self.versions)
|
||||
self.api.add_route("/version/{version_id}", self.versions)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
other:
|
||||
- |
|
||||
Enabled possibility of specifying the CLI arguments, when launching
|
||||
monasca-log-api, for cases where API is not deployed using Gunicorn
|
||||
server.
|
Loading…
Reference in New Issue