Add tests for events

Story: 2004549
Task: 28302
Change-Id: Id505116637ac66de349962c9f804ddaa14601475
This commit is contained in:
Adrian Czarnecki 2018-09-04 14:11:04 +02:00
parent fa5f826138
commit f1d457fc79
7 changed files with 272 additions and 5 deletions

View File

@ -0,0 +1,35 @@
# Copyright 2019 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_tempest_tests.services import elasticsearch_client
from monasca_tempest_tests.services import events_api_client
class Manager(clients.Manager):
def __init__(self, credentials=None):
super(Manager, self).__init__(credentials)
self.events_api_client = events_api_client.EventApiClient(
self.auth_provider,
'events',
None
)
self.events_search_client = elasticsearch_client.ElasticsearchClient(
self.auth_provider,
'events-search',
None
)

View File

@ -14,8 +14,8 @@
from tempest import clients from tempest import clients
from monasca_tempest_tests.services import elasticsearch_client
from monasca_tempest_tests.services import log_api_v3_client from monasca_tempest_tests.services import log_api_v3_client
from monasca_tempest_tests.services import log_search_client
class Manager(clients.Manager): class Manager(clients.Manager):
@ -28,7 +28,7 @@ class Manager(clients.Manager):
None None
) )
self.log_search_client = log_search_client.LogsSearchClient( self.log_search_client = elasticsearch_client.ElasticsearchClient(
self.auth_provider, self.auth_provider,
'logs-search', 'logs-search',
None None

View File

@ -12,16 +12,19 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from oslo_config import cfg
from oslo_serialization import jsonutils as json from oslo_serialization import jsonutils as json
from six import PY3 from six import PY3
from tempest.lib.common import rest_client from tempest.lib.common import rest_client
CONF = cfg.CONF
class LogsSearchClient(rest_client.RestClient):
class ElasticsearchClient(rest_client.RestClient):
uri_prefix = "/elasticsearch" uri_prefix = "/elasticsearch"
def __init__(self, auth_provider, service, region): def __init__(self, auth_provider, service, region):
super(LogsSearchClient, self).__init__( super(ElasticsearchClient, self).__init__(
auth_provider, auth_provider,
service, service,
region, region,
@ -49,7 +52,7 @@ class LogsSearchClient(rest_client.RestClient):
def count_search_messages(self, message, headers): def count_search_messages(self, message, headers):
return len(self.search_messages(message, headers)) return len(self.search_messages(message, headers))
def search_messages(self, message, headers): def search_messages(self, message, headers=None):
uri = '_msearch' uri = '_msearch'
body = """ body = """
{"index" : "*", "search_type" : "dfs_query_then_fetch"} {"index" : "*", "search_type" : "dfs_query_then_fetch"}
@ -60,5 +63,30 @@ class LogsSearchClient(rest_client.RestClient):
body = self.deserialize(body) body = self.deserialize(body)
return body['responses'][0].get('hits', {}).get('hits', []) return body['responses'][0].get('hits', {}).get('hits', [])
def search_event_by_event_type(self, event_type):
uri = '_msearch'
body = """
{"index" : "*", "search_type" : "dfs_query_then_fetch"}
{"query" : {"match" : {"event_type":" """ + event_type + """ "}}}
"""
header = {'kbn-version': CONF.monitoring.kibana_version}
response, body = self.post(self._uri(uri), body, header)
self.expected_success(200, response.status)
body = self.deserialize(body)
return body['responses'][0].get('hits', {}).get('hits', [])
def search_event(self, event):
uri = '_msearch'
header = {'kbn-version': CONF.monitoring.kibana_version}
event = json.dumps(event)
body = """
{"index" : "*", "search_type" : "dfs_query_then_fetch"}
{"query" : {"match" : {"event":" """ + event + """ "}}}
"""
response, body = self.post(self._uri(uri), body, header)
self.expected_success(200, response.status)
body = self.deserialize(body)
return body['responses'][0].get('hits', {}).get('hits', [])
def _uri(self, url): def _uri(self, url):
return '{}/{}'.format(self.uri_prefix, url) return '{}/{}'.format(self.uri_prefix, url)

View File

@ -0,0 +1,34 @@
# Copyright 2019 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 json
from tempest.lib.common import rest_client
class EventApiClient(rest_client.RestClient):
_uri = '/v1.0/events'
def __init__(self, auth_provider, service, region):
super(EventApiClient, self).__init__(
auth_provider,
service,
region
)
def send_events(self, events, headers=None):
msg = json.dumps(events)
resp, body = self.post(self._uri, body=msg, headers=headers)
return resp, body

View File

@ -0,0 +1,94 @@
# Copyright 2019 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 datetime import datetime
import json
from os import path
import pytz
import random
import string
from oslo_config import cfg
from tempest.common import credentials_factory as cred_factory
from tempest import test
from monasca_tempest_tests.clients import event_api as clients
CONF = cfg.CONF
def get_simple_event():
json_file_path = path.join(path.dirname(__file__),
'req_simple_event.json')
with open(json_file_path, 'r') as f:
return json.loads(f.read())
def create_header(header={}, content_type='application/json'):
header.update({'Content-Type': content_type,
'kbn-version': CONF.monitoring.kibana_version})
return header
def generate_simple_event_type_string():
letters = string.ascii_lowercase
random_string = ''.join((random.choice(letters) for _ in range(15)))
return '{}.{}'.format(random_string[:7], random_string[8:])
def generate_simple_event(event_type=None, timestamp=None, events=None, num_of_events=1):
if event_type is None:
event_type = generate_simple_event_type_string()
if events is None:
events = \
[{
'dimensions': {
'service': 'compute',
'topic': 'notification.sample',
'hostname': 'mars'},
'project_id': '6f70656e737461636b20342065766572',
'event': {
'event_type': event_type,
'payload': {
'nova_object.data': {
'architecture': 'x86_64',
'availability_zone': 'nova',
'created_at': '2012-10-29T13:42:11Z'}}}}] \
* num_of_events
if timestamp is None:
timestamp = datetime.now(tz=pytz.utc).strftime("%Y-%m-%dT%H:%M:%SZ%z")
return {'timestamp': timestamp,
'events': events}
class BaseEventsTestCase(test.BaseTestCase):
"""Base test case class for all Event API tests."""
@classmethod
def skip_checks(cls):
super(BaseEventsTestCase, cls).skip_checks()
@classmethod
def resource_setup(cls):
super(BaseEventsTestCase, 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(
['admin']).credentials
cls.os_primary = clients.Manager(credentials=credentials)
cls.events_api_client = cls.os_primary.events_api_client
cls.events_search_client = cls.os_primary.events_search_client

View File

@ -0,0 +1,76 @@
# Copyright 2019 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 tempest.lib import exceptions
from monasca_tempest_tests.tests.event_api import base
RETRY_COUNT = 15
RETRY_WAIT = 2
class BaseEventsTestCase(base.BaseEventsTestCase):
def check_if_events_are_present_in_db(self, event_type):
return len(self.events_search_client.search_event_by_event_type(event_type)) > 0
def send_and_retrieve_events(self, events=None, header=None, events_number=1):
if events is None:
event_type = base.generate_simple_event_type_string()
events = base.generate_simple_event(event_type, num_of_events=events_number)
if header is None:
header = base.create_header()
response, _ = self.events_api_client.send_events(events, header)
self.assertEqual(200, response.status)
test_utils.call_until_true(self.check_if_events_are_present_in_db,
RETRY_COUNT * RETRY_WAIT,
RETRY_WAIT,
event_type)
response = self.events_search_client.search_event_by_event_type(event_type)
self.assertEqual(events_number, len(response))
@decorators.attr(type=['gate', 'smoke'])
def test_single_event(self):
self.send_and_retrieve_events()
@decorators.attr(type='gate')
def test_multiple_events(self):
self.send_and_retrieve_events(events_number=5)
@decorators.attr(type='gate')
def test_missing_body(self):
header = base.create_header()
try:
response, _ = self.events_api_client.send_events(None, header)
except exceptions.UnprocessableEntity as exc:
self.assertEqual(422, exc.resp.status)
@decorators.attr(type='gate')
def test_empty_event(self):
header = base.create_header()
body = base.generate_simple_event(events=[])
try:
response, _ = self.events_api_client.send_events(body, header)
except exceptions.UnprocessableEntity as exc:
self.assertEqual(422, exc.resp.status)
def test_empty_content_type(self):
body = base.generate_simple_event()
try:
response, _ = self.events_api_client.send_events(body, {})
except exceptions.BadRequest as exc:
self.assertEqual(400, exc.resp.status)