Merge "Remove bundled intree tempest plugin"

This commit is contained in:
Zuul 2018-04-30 10:36:15 +00:00 committed by Gerrit Code Review
commit f15240f028
17 changed files with 0 additions and 929 deletions

0
contrib/post_test_hook.sh Executable file → Normal file
View File

View File

@ -1,211 +0,0 @@
# Introduction
**Monasca-Log-Api** requires following components set up in the environment:
* monasca-log-transformer - component receiving data from monasca-log-api, [config](../devstack/files/transformer.conf)
* monasca-log-persister - component saves data to ElasticSearch, [config](../devstack/files/persister.conf)
* ElasticSearch - database that stores logs, [config](../devstack/files/elasticsearch.yml)
Those three components are all part of [devstack](https://github.com/openstack/monasca-api/tree/master/devstack).
* Logstash - it is a prerequisite for monasca-log-transformer and monasca-log-persister components
**Monasca-Log-Api** can be installed using following [Github repo](https://github.com/openstack/monasca-log-api/).
In order to setup schema (kafka topics) please see [this](https://github.com/openstack/monasca-log-api/blob/master/devstack/plugin.sh#L198).
## Installation next to monasca-api
**Monasca-Api** and **Monasca-Log-Api** can be installed next to each other.
Each one has been designed to work with different aspects of monitoring.
Therefore it is possible to proceed with installation as described
[here](https://github.com/openstack/monasca-log-api/blob/master/devstack/).
# Configuration
1. Clone the OpenStack Tempest repo, and cd to it.
```bash
git clone https://git.openstack.org/openstack/tempest.git
cd tempest
```
2. Create a virtualenv for running the Tempest tests and activate it.
For example in the Tempest root dir
```bash
virtualenv .venv
source .venv/bin/activate
```
3. Install the Tempest requirements in the virtualenv.
```bash
pip install \
-c https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt \
-r requirements.txt \
-r test-requirements.txt
```
4. Create ```etc/tempest.conf``` in the Tempest root dir by
running the following command:
```bash
oslo-config-generator --config-file tempest/cmd/config-generator.tempest.conf --output-file etc/tempest.conf
```
Add the following sections to ```tempest.conf``` for testing
using the monasca-vagrant environment.
```ini
[identity]
region = RegionOne
auth_version = v3
uri = http://10.36.99.238/identity_admin/v2.0
uri_v3 = http://10.36.99.238/identity_admin/v3
user_lockout_failure_attempts = 2
user_locakout_duration = 5
user_unique_last_password_count = 2
admin_domain_scope = True
[auth]
tempest_roles = monasca-user
admin_project_name = admin
admin_domain_name = default
admin_password = secretadmin
admin_username = admin
use_dynamic_credentials = True
[monitoring]
kibana_version = 4.6.3
api_version = v2.0 # or v3.0
```
Edit the variable values in the identity section to match your particular
monasca-vagrant environment. Best way to do this might be
```bash
source devstack/openrc {username} {password}
```
and collect all relevant values using
```bash
env | grep OS_
```
An output will be similar to this one
```bash
OS_PROJECT_DOMAIN_ID=default
OS_REGION_NAME=RegionOne
OS_USER_DOMAIN_ID=default
OS_PROJECT_NAME=admin
OS_IDENTITY_API_VERSION=3
OS_PASSWORD=secretadmin
OS_AUTH_TYPE=password
OS_AUTH_URL=http://10.36.99.238/identity_admin
OS_USERNAME=admin
OS_TENANT_NAME=admin
OS_VOLUME_API_VERSION=2
OS_NO_CACHE=True
```
5. Create ```etc/logging.conf``` in the Tempest root dir by making a copying
```logging.conf.sample```.
6. Clone the monasca-log-api repo in a directory somewhere outside of the
Tempest root dir.
7. Install the monasca-log-api in your venv, which will also register
the Monasca Log Api Tempest Plugin as, monasca_log_api_tempest.
cd into the monasca-log-api root directory. Making sure that the tempest
virtual env is still active, run the following command.
```
pip install \
-c https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt \
-r requirements.txt \
-r test-requirements.txt
python setup.py install
```
See the [OpenStack Tempest Plugin
Interface](https://docs.openstack.org/tempest/latest/plugin.html), for more
details on Tempest Plugins and the plugin registration process.
# Running the Monasca Log Api Tempest
The Monasca Tempest Tests can be run using a variety of methods including:
1. [Testr](https://wiki.openstack.org/wiki/Testr)
2. [Os-testr](https://docs.openstack.org/os-testr/latest/)
3. [PyCharm](https://www.jetbrains.com/pycharm/)
4. Tempest Scripts in Devstack
## Run the tests from the CLI using testr
[Testr](https://wiki.openstack.org/wiki/Testr) is a test runner that can be used to run the Tempest tests.
1. In the Tempest root dir, create a list of the Monasca Tempest Tests in a file.
```sh
testr list-tests monasca_log_api_tempest > monasca_log_api_tempest
```
2. Run the tests using testr
```sh
testr run --load-list=monasca_log_api_tempest
```
You can also use testr to create a list of specific tests for your needs.
## Run the tests from the CLI using os-testr (no file necessary)
[Os-testr](https://docs.openstack.org/os-testr/latest/) is a test wrapper
that can be used to run the Monasca Tempest tests.
1. In the Tempest root dir:
```
ostestr --serial --regex monasca_log_api_tempest
```
```--serial``` option is necessary here. Monasca Log Api tempest tests can't
be run in parallel (default option in ostestr) because some tests depend on the
same data and will randomly fail.
## Running/Debugging the Monasca Tempest Tests in PyCharm
Assuming that you have already created a PyCharm project for the
```monasca-log-api``` do the following:
1. In PyCharm, Edit Configurations and add a new Python tests configuration by selecting Python tests->Nosetests.
2. Name the test. For example TestSingleLog.
3. Set the path to the script with the tests to run. For example, ~/repos/monasca-log-api/monasca_log_api_tempest/tests/test_single.py
4. Set the name of the Class to test. For example TestVersions.
5. Set the working directory to your local root Tempest repo. For example, ~/repos/tempest.
6. Select the Python interpreter for your project to be the same as the one virtualenv created above. For example, ~/repos/tempest/.venv
7. Run the tests. You should also be able to debug them.
8. Step and repeat for other tests.
## Run the tests from the CLI using tempest scripts in devstack
1. In /opt/stack/tempest, run ```./run_tempest.sh monasca_log_api_tempest```
2. If asked to create a new virtual environment, select yes
3. Activate the virtual environment ```source .venv/bin/activate```
4. In your monasca-log-api directory, run ```python setup.py install```
5. In /opt/stack/tempest, run ```./run_tempest.sh monasca_log_api_tempest```
# References
This section provides a few additional references that might be useful:
* [Tempest - The OpenStack Integration Test Suite](https://docs.openstack.org/tempest/latest/overview.html#quickstart)
* [Tempest Configuration Guide](https://github.com/openstack/tempest/blob/master/doc/source/configuration.rst#id1)
* [OpenStack Tempest Plugin Interface](https://docs.openstack.org/tempest/latest/plugin.html)
In addition to the above references, another source of information is the following OpenStack projects:
* [Manila Tempest Tests](https://github.com/openstack/manila/tree/master/manila_tempest_tests)
* [Congress Tempest Tests](https://github.com/openstack/congress/tree/master/congress_tempest_tests).
In particular, the Manila Tempest Tests were used as a reference implementation to develop the Monasca Tempest Tests.
There is also a wiki [HOWTO use tempest with manila](https://wiki.openstack.org/wiki/Manila/docs/HOWTO_use_tempest_with_manila) that might be useful for Monasca too.
# Issues
* Update documentation for testing using Devstack when available.
* Consider changing from monasca_tempest_tests to monasca_api_tempest_tests.

View File

@ -1,42 +0,0 @@
# Copyright 2015-2016 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.
from tempest import clients
from monasca_log_api_tempest.services import log_api_v2_client
from monasca_log_api_tempest.services import log_api_v3_client
from monasca_log_api_tempest.services import log_search_client
class Manager(clients.Manager):
def __init__(self, credentials=None):
super(Manager, self).__init__(credentials)
self.log_api_clients = {
"v2": log_api_v2_client.LogApiV2Client(
self.auth_provider,
'logs_v2',
None
),
"v3": log_api_v3_client.LogApiV3Client(
self.auth_provider,
'logs',
None
)
}
self.log_search_client = log_search_client.LogsSearchClient(
self.auth_provider,
'logs-search',
None
)

View File

@ -1,39 +0,0 @@
# Copyright 2015 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.
from oslo_config import cfg
service_available_group = cfg.OptGroup(name='service_available',
title='Available OpenStack Services')
ServiceAvailableGroup = [
cfg.BoolOpt('logs',
default=True,
help=('Whether or not Monasca-Log-Api '
'is expected to be available')),
cfg.BoolOpt('logs-search',
default=True,
help=('Whether or not Monasca-Log-Api search engine '
'(ElasticSearch) is expected to be available'))
]
monitoring_group = cfg.OptGroup(name='monitoring',
title='Monitoring Service Options')
MonitoringGroup = [
cfg.StrOpt('api_version',
default='v2.0',
help='monasca-log-api API version'),
cfg.StrOpt('kibana_version',
default='4.6.3',
help='Kibana version')
]

View File

@ -1,45 +0,0 @@
# Copyright 2015 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 os
from tempest import config
from tempest.test_discover import plugins
from monasca_log_api_tempest import config as config_log_api
_ROOT_PCKG_NAME = "monasca_log_api_tempest"
class MonascaLogApiTempestPlugin(plugins.TempestPlugin):
def load_tests(self):
base_path = os.path.split(os.path.dirname(
os.path.abspath(__file__)))[0]
test_dir = "%s/tests" % _ROOT_PCKG_NAME
full_test_dir = os.path.join(base_path, test_dir)
return full_test_dir, base_path
def register_opts(self, conf):
config.register_opt_group(
conf,
config_log_api.service_available_group,
config_log_api.ServiceAvailableGroup
)
config.register_opt_group(conf,
config_log_api.monitoring_group,
config_log_api.MonitoringGroup)
def get_opt_lists(self):
return [(config_log_api.monitoring_group.name,
config_log_api.MonitoringGroup)]

View File

@ -1,51 +0,0 @@
# Copyright 2015 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.
from oslo_serialization import jsonutils as json
from tempest.lib.common import rest_client
class LogApiV2Client(rest_client.RestClient):
_uri = "/log/single"
def __init__(self, auth_provider, service, region):
super(LogApiV2Client, self).__init__(
auth_provider,
service,
region
)
def get_version(self):
resp, response_body = self.send_request('GET', '/')
return resp, response_body
def send_single_log(self,
log,
headers=None,
fields=None):
default_headers = {
'X-Tenant-Id': 'b4265b0a48ae4fd3bdcee0ad8c2b6012',
'X-Roles': 'admin',
'X-Dimensions': 'dev:tempest'
}
default_headers.update(headers)
msg = json.dumps(log)
resp, body = self.post(LogApiV2Client._uri, msg, default_headers)
return resp, body
def custom_request(self, method, headers=None, body=None):
self.request(method=method, url=LogApiV2Client._uri, headers=headers, body=body)

View File

@ -1,52 +0,0 @@
# Copyright 2015 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.
from oslo_serialization import jsonutils as json
from six.moves.urllib.parse import urlencode
from tempest.lib.common import rest_client
class LogApiV3Client(rest_client.RestClient):
_uri = "/logs"
def __init__(self, auth_provider, service, region):
super(LogApiV3Client, self).__init__(
auth_provider,
service,
region
)
def get_version(self):
resp, response_body = self.send_request('GET', '/')
return resp, response_body
def send_single_log(self, log, headers=None, fields=None):
default_headers = {
'X-Tenant-Id': 'b4265b0a48ae4fd3bdcee0ad8c2b6012',
'X-Roles': 'admin',
}
default_headers.update(headers)
msg = json.dumps(log)
uri = LogApiV3Client._uri
if fields:
uri += '?' + urlencode(fields)
resp, body = self.post(uri, msg, default_headers)
return resp, body
def custom_request(self, method, headers=None, body=None):
self.request(method=method, url=LogApiV3Client._uri, headers=headers, body=body)

View File

@ -1,62 +0,0 @@
# Copyright 2015 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.
from oslo_serialization import jsonutils as json
from tempest.lib.common import rest_client
class LogsSearchClient(rest_client.RestClient):
uri_prefix = "/elasticsearch"
def __init__(self, auth_provider, service, region):
super(LogsSearchClient, self).__init__(
auth_provider,
service,
region,
)
@staticmethod
def deserialize(body):
return json.loads(body.replace("\n", ""))
@staticmethod
def serialize(body):
return json.dumps(body)
def get_metadata(self):
uri = "/"
response, body = self.get(self._uri(uri))
self.expected_success(200, response.status)
if body:
body = self.deserialize(body)
return response, body
def count_search_messages(self, message, headers):
return len(self.search_messages(message, headers))
def search_messages(self, message, headers):
uri = '_msearch'
body = """
{"index" : "*", "search_type" : "dfs_query_then_fetch"}
{"query" : {"match" : {"message":" """+message+""" "}}}
"""
response, body = self.post(self._uri(uri), body, headers)
self.expected_success(200, response.status)
body = self.deserialize(body)
return body['responses'][0].get('hits', {}).get('hits', [])
def _uri(self, url):
return '{}/{}'.format(self.uri_prefix, url)

View File

@ -1,125 +0,0 @@
# Copyright 2015 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 random
import string
from oslo_config import cfg
from tempest.common import credentials_factory as cred_factory
from tempest import test
from tempest import exceptions
from monasca_log_api_tempest import clients
CONF = cfg.CONF
_ONE_MB = 1024 * 1024 # MB
def _get_message_size(size_base):
"""Returns message size in number of characters.
Method relies on UTF-8 where 1 character = 1 byte.
"""
return int(round(size_base * _ONE_MB, 1))
_SMALL_MESSAGE_SIZE = _get_message_size(0.001)
_MEDIUM_MESSAGE_SIZE = _get_message_size(0.01)
_LARGE_MESSAGE_SIZE = _get_message_size(0.1)
_REJECTABLE_MESSAGE_SIZE = _get_message_size(1.1)
def generate_unique_message(message=None, size=50):
letters = string.ascii_lowercase
def rand(amount, space=True):
space = ' ' if space else ''
return ''.join((random.choice(letters + space) for _ in range(amount)))
sid = rand(10, space=False)
if not message:
message = rand(size)
return sid, sid + ' ' + message
def generate_small_message(message=None):
return generate_unique_message(message, _SMALL_MESSAGE_SIZE)
def generate_medium_message(message=None):
return generate_unique_message(message, _MEDIUM_MESSAGE_SIZE)
def generate_large_message(message=None):
return generate_unique_message(message, _LARGE_MESSAGE_SIZE)
def generate_rejectable_message(message=None):
return generate_unique_message(message, _REJECTABLE_MESSAGE_SIZE)
def _get_headers(headers=None, content_type="application/json"):
if not headers:
headers = {}
headers.update({
'Content-Type': content_type,
'kbn-version': CONF.monitoring.kibana_version
})
return headers
def _get_data(message, content_type="application/json", version="v3"):
if version == "v3":
data = {
'logs': [{
'message': message
}]
}
elif 'application/json' == content_type:
data = {
'message': message
}
return data
class BaseLogsTestCase(test.BaseTestCase):
"""Base test case class for all Monitoring API tests."""
@classmethod
def skip_checks(cls):
super(BaseLogsTestCase, cls).skip_checks()
@classmethod
def resource_setup(cls):
super(BaseLogsTestCase, cls).resource_setup()
auth_version = CONF.identity.auth_version
cred_provider = cred_factory.get_credentials_provider(
cls.__name__,
identity_version=auth_version)
credentials = cred_provider.get_creds_by_roles(
['monasca-user', 'admin']).credentials
cls.os_primary = clients.Manager(credentials=credentials)
cls.logs_clients = cls.os_primary.log_api_clients
cls.logs_search_client = cls.os_primary.log_search_client
@staticmethod
def cleanup_resources(method, list_of_ids):
for resource_id in list_of_ids:
try:
method(resource_id)
except exceptions.EndpointNotFound:
pass

View File

@ -1,107 +0,0 @@
# Copyright 2015-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.
from tempest.lib import decorators
from tempest.lib import exceptions
from monasca_log_api_tempest.tests import base
class TestLogApiConstraints(base.BaseLogsTestCase):
@decorators.attr(type='gate')
def test_should_reject_if_body_is_empty(self):
headers = base._get_headers()
for cli in self.logs_clients.itervalues():
try:
cli.custom_request('POST', headers, None)
except exceptions.UnprocessableEntity as urc:
# depending on the actual server (for example gunicorn vs mod_wsgi)
# monasca-log-api may return a different error code
self.assertTrue(urc.resp.status in [411, 422])
return
self.assertTrue(False, 'API should respond with an error')
@decorators.attr(type='gate')
def test_should_reject_if_content_type_missing(self):
headers = base._get_headers(content_type='')
for cli in self.logs_clients.itervalues():
try:
cli.custom_request('POST', headers, '{}')
except exceptions.BadRequest as urc:
self.assertEqual(400, urc.resp.status)
return
self.assertTrue(False, 'API should respond with 400')
@decorators.attr(type='gate')
def test_should_reject_if_wrong_content_type(self):
headers = base._get_headers(content_type='video/3gpp')
for cli in self.logs_clients.itervalues():
try:
cli.custom_request('POST', headers, '{}')
except exceptions.InvalidContentType as urc:
self.assertEqual(415, urc.resp.status)
return
self.assertTrue(False, 'API should respond with 400')
@decorators.attr(type='gate')
def test_should_reject_too_big_message(self):
_, message = base.generate_rejectable_message()
headers = base._get_headers(self.logs_clients["v3"].get_headers())
# Add 'Connection: Keep-Alive' to send large message before
# connection is closed by client. In class ClosingHttp is added
# header 'connection:close' (which will cause closing socket before sending whole message).
# Data are send in small TCP packages.
# Without this header set to Keep-Alive Tempest lib will try to retry connection and finally
# raise ProtocolError.
headers.update({'Connection': 'Keep-Alive'})
for ver, cli in self.logs_clients.items():
data = base._get_data(message, version=ver)
try:
cli.send_single_log(data, headers)
except exceptions.OverLimit as urc:
self.assertEqual(413, urc.resp.status)
return
except exceptions.UnexpectedContentType as uct:
self.assertEqual(503, uct.resp.status)
return
self.assertTrue(False, 'API should respond with 413 or 503')
@decorators.attr(type='gate')
def test_should_reject_too_big_message_multiline(self):
_, message = base.generate_rejectable_message()
message = message.replace(' ', '\n')
headers = base._get_headers(self.logs_clients["v3"].get_headers())
# Add Connection: Keep-Alive to send large message before
# connection is closed by cli. In class ClosingHttp is added
# header connection:close (which will cause closing socket before sending whole message).
# Data are send in small TCP packages.
# Without this header set to Keep-Alive Tempest lib will try to retry connection and finally
# raise ProtocolError.
headers.update({'Connection': 'Keep-Alive'})
for ver, cli in self.logs_clients.items():
data = base._get_data(message, version=ver)
try:
cli.send_single_log(data, headers)
except exceptions.OverLimit as urc:
self.assertEqual(413, urc.resp.status)
return
except exceptions.UnexpectedContentType as uct:
self.assertEqual(503, uct.resp.status)
return
self.assertTrue(False, 'API should respond with 413 or 503')

View File

@ -1,128 +0,0 @@
# Copyright 2015-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.
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from testtools import matchers
from monasca_log_api_tempest.tests import base
_RETRY_COUNT = 15
_RETRY_WAIT = 2
class TestSingleLog(base.BaseLogsTestCase):
def _run_and_wait(self, key, data, version,
content_type='application/json',
headers=None, fields=None):
headers = base._get_headers(headers, content_type)
def wait():
return self.logs_search_client.count_search_messages(key,
headers) > 0
self.assertEqual(0, self.logs_search_client.count_search_messages(key,
headers),
'Find log message in elasticsearch: {0}'.format(key))
headers = base._get_headers(headers, content_type)
data = base._get_data(data, content_type, version=version)
client = self.logs_clients[version]
response, _ = client.send_single_log(data, headers, fields)
self.assertEqual(204, response.status)
test_utils.call_until_true(wait, _RETRY_COUNT * _RETRY_WAIT,
_RETRY_WAIT)
response = self.logs_search_client.search_messages(key, headers)
self.assertEqual(1, len(response))
return response
@decorators.attr(type="gate")
def test_small_message(self):
for ver in self.logs_clients:
self._run_and_wait(*base.generate_small_message(), version=ver)
@decorators.attr(type="gate")
def test_medium_message(self):
for ver in self.logs_clients:
self._run_and_wait(*base.generate_medium_message(), version=ver)
@decorators.attr(type="gate")
def test_big_message(self):
for ver in self.logs_clients:
self._run_and_wait(*base.generate_large_message(), version=ver)
@decorators.attr(type="gate")
def test_small_message_multiline(self):
for ver in self.logs_clients:
sid, message = base.generate_small_message()
self._run_and_wait(sid, message.replace(' ', '\n'), version=ver)
@decorators.attr(type="gate")
def test_medium_message_multiline(self):
for ver in self.logs_clients:
sid, message = base.generate_medium_message()
self._run_and_wait(sid, message.replace(' ', '\n'), version=ver)
@decorators.attr(type="gate")
def test_big_message_multiline(self):
for ver in self.logs_clients:
sid, message = base.generate_large_message()
self._run_and_wait(sid, message.replace(' ', '\n'), version=ver)
@decorators.attr(type="gate")
def test_send_header_application_type(self):
sid, message = base.generate_unique_message()
headers = {'X-Application-Type': 'application-type-test'}
response = self._run_and_wait(sid, message, headers=headers,
version="v2")
self.assertEqual('application-type-test',
response[0]['_source']['component'])
@decorators.attr(type="gate")
def test_send_header_dimensions(self):
sid, message = base.generate_unique_message()
headers = {'X-Dimensions':
'server:WebServer01,environment:production'}
response = self._run_and_wait(sid, message, headers=headers,
version="v2")
self.assertEqual('production', response[0]['_source']['environment'])
self.assertEqual('WebServer01', response[0]['_source']['server'])
@decorators.attr(type="gate")
def test_send_cross_tenant(self):
sid, message = base.generate_small_message()
headers = {'X-Roles': 'admin, monitoring-delegate'}
cross_tennant_id = '2106b2c8da0eecdb3df4ea84a0b5624b'
fields = {'tenant_id': cross_tennant_id}
response = self._run_and_wait(sid, message, version="v3",
headers=headers, fields=fields)
self.assertThat(response[0]['_source']['tenant'],
matchers.StartsWith(cross_tennant_id))
# TODO(trebski) following test not passing - failed to retrieve
# big message from elasticsearch
# @decorators.attr(type='gate')
# def test_should_truncate_big_message(self):
# message_size = base._get_message_size(0.9999)
# sid, message = base.generate_unique_message(size=message_size)
#
# headers = base._get_headers(self.logs_clients.get_headers())
# response = self._run_and_wait(sid, message, headers=headers)
#
# self.assertTrue(False, 'API should respond with 500')

View File

@ -1,63 +0,0 @@
# 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.
from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
from monasca_log_api.tests import base as api_base
from monasca_log_api_tempest.tests import base
_API_VERSION = 'v3'
_RETRY_COUNT = 15
_RETRY_WAIT = 2
_UNICODE_CASES = api_base.UNICODE_MESSAGES
class TestUnicodeV3(base.BaseLogsTestCase):
def _run_and_wait(self, key, data,
content_type='application/json',
headers=None, fields=None):
headers = base._get_headers(headers, content_type)
def wait():
return self.logs_search_client.count_search_messages(key,
headers) > 0
self.assertEqual(0, self.logs_search_client.count_search_messages(key,
headers),
'Find log message in elasticsearch: {0}'.format(key))
headers = base._get_headers(headers, content_type)
data = base._get_data(data, content_type, version=_API_VERSION)
client = self.logs_clients[_API_VERSION]
response, _ = client.send_single_log(data, headers, fields)
self.assertEqual(204, response.status)
test_utils.call_until_true(wait, _RETRY_COUNT * _RETRY_WAIT,
_RETRY_WAIT)
response = self.logs_search_client.search_messages(key, headers)
self.assertEqual(1, len(response))
return response
@decorators.attr(type="gate")
def test_unicode_message(self):
for m in _UNICODE_CASES:
case, msg = m.values()
self._run_and_wait(*base.generate_small_message(msg), headers={
'LA-Unicode-Case': case
})

View File

@ -25,7 +25,6 @@ setup-hooks =
[files]
packages =
monasca_log_api
monasca_log_api_tempest
data_files =
etc/monasca =
@ -39,9 +38,6 @@ console_scripts =
wsgi_scripts =
monasca-log-api-wsgi = monasca_log_api.app.wsgi:main
tempest.test_plugins =
monasca_log_api_tests = monasca_log_api_tempest.plugin:MonascaLogApiTempestPlugin
oslo.config.opts =
monasca_log_api = monasca_log_api.conf:list_opts