sync vitrage tempest
Change-Id: Ibbdc14af3d2b15c119c87d875ab5ec41c08f5f07
This commit is contained in:
parent
1c6f0668a9
commit
e7d594e4a5
@ -13,12 +13,9 @@
|
||||
# under the License.
|
||||
import sys
|
||||
|
||||
from vitrage.common.constants import TemplateStatus
|
||||
from vitrage.common.constants import TemplateTypes as TType
|
||||
from vitrage.evaluator.template_db.template_repository import \
|
||||
add_template_to_db
|
||||
from vitrage import service
|
||||
from vitrage import storage
|
||||
from vitrage.tests.functional.test_configuration import TestConfiguration
|
||||
from vitrage_tempest_tests.tests.common import general_utils
|
||||
|
||||
files = ['corrupted_template.yaml', 'e2e_test_basic_actions.yaml',
|
||||
@ -32,12 +29,10 @@ def main():
|
||||
resources_path = general_utils.tempest_resources_dir() + '/templates/api/'
|
||||
conf = service.prepare_service()
|
||||
db = storage.get_connection_from_config(conf)
|
||||
TestConfiguration._db = db
|
||||
for f in files:
|
||||
full_path = resources_path + f
|
||||
template = add_template_to_db(db, full_path, TType.STANDARD)
|
||||
if template[0]['name'] != 'corrupted_template':
|
||||
db.templates.update(template[0]['uuid'],
|
||||
'status', TemplateStatus.ACTIVE)
|
||||
TestConfiguration.add_templates(full_path)
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
@ -18,8 +18,7 @@ from oslo_log import log as logging
|
||||
|
||||
from vitrage.common.constants import TemplateStatus
|
||||
from vitrage.common.constants import TemplateTypes as TTypes
|
||||
from vitrage.evaluator.template_db.template_repository import \
|
||||
load_template_file
|
||||
from vitrage.utils import file
|
||||
from vitrage_tempest_tests.tests.api.templates.base import BaseTemplateTest
|
||||
from vitrage_tempest_tests.tests.common import general_utils as g_utils
|
||||
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
|
||||
@ -285,7 +284,7 @@ class TemplatesDBTest(BaseTemplateTest):
|
||||
type=TTypes.STANDARD,
|
||||
status=TemplateStatus.ACTIVE)
|
||||
payload_from_db = self.client.template.show(db_row['uuid'])
|
||||
payload_from_file = load_template_file(template_path)
|
||||
payload_from_file = file.load_yaml_file(template_path)
|
||||
self.assertEqual(payload_from_file, payload_from_db,
|
||||
"Template content doesn't match")
|
||||
vitrage_utils.delete_template(db_row['uuid'])
|
||||
|
15
vitrage_tempest_tests/tests/api/webhook/__init__.py
Normal file
15
vitrage_tempest_tests/tests/api/webhook/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
# Copyright 2017 - Nokia
|
||||
#
|
||||
# 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__ = 'stack'
|
149
vitrage_tempest_tests/tests/api/webhook/test_webhook.py
Normal file
149
vitrage_tempest_tests/tests/api/webhook/test_webhook.py
Normal file
@ -0,0 +1,149 @@
|
||||
# Copyright 2017 Nokia
|
||||
#
|
||||
# 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_log import log as logging
|
||||
|
||||
from vitrage_tempest_tests.tests.base import BaseVitrageTempest
|
||||
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
|
||||
from vitrageclient.exceptions import ClientException
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
URL = 'url'
|
||||
REGEX_FILTER = 'regex_filter'
|
||||
HEADERS = 'headers'
|
||||
HEADERS_PROPS = '{"content": "application/json"}'
|
||||
REGEX_PROPS = '{"name": "e2e.*"}'
|
||||
|
||||
|
||||
class TestWebhook(BaseVitrageTempest):
|
||||
"""Webhook test class for Vitrage API tests."""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestWebhook, cls).setUpClass()
|
||||
cls.pre_test_webhook_count = \
|
||||
len(TempestClients.vitrage().webhook.list())
|
||||
|
||||
def test_add_webhook(self):
|
||||
|
||||
webhooks = TempestClients.vitrage().webhook.list()
|
||||
self.assertEqual(self.pre_test_webhook_count,
|
||||
len(webhooks),
|
||||
'Amount of webhooks should be the same as '
|
||||
'before the test')
|
||||
|
||||
created_webhook = TempestClients.vitrage().webhook.add(
|
||||
url="https://www.test.com",
|
||||
regex_filter=REGEX_PROPS,
|
||||
headers=HEADERS_PROPS
|
||||
)
|
||||
|
||||
self.assertIsNone(created_webhook.get('ERROR'), 'webhook not '
|
||||
'created')
|
||||
self.assertEqual(created_webhook[HEADERS],
|
||||
HEADERS_PROPS,
|
||||
'headers not created correctly')
|
||||
self.assertEqual(created_webhook[REGEX_FILTER],
|
||||
REGEX_PROPS,
|
||||
'regex not created correctly')
|
||||
self.assertEqual(created_webhook[URL],
|
||||
"https://www.test.com",
|
||||
'URL not created correctly')
|
||||
|
||||
webhooks = TempestClients.vitrage().webhook.list()
|
||||
|
||||
self.assertEqual(self.pre_test_webhook_count + 1, len(webhooks))
|
||||
TempestClients.vitrage().webhook.delete(
|
||||
created_webhook['id'])
|
||||
|
||||
def test_delete_webhook(self):
|
||||
webhooks = TempestClients.vitrage().webhook.list()
|
||||
self.assertEqual(self.pre_test_webhook_count,
|
||||
len(webhooks),
|
||||
'Amount of webhooks should be the same as '
|
||||
'before the test')
|
||||
|
||||
created_webhook = TempestClients.vitrage().webhook.add(
|
||||
url="https://www.test.com",
|
||||
regex_filter=REGEX_PROPS,
|
||||
headers=HEADERS_PROPS
|
||||
)
|
||||
|
||||
created_webhook = TempestClients.vitrage().webhook.delete(
|
||||
id=created_webhook['id'])
|
||||
self.assertIsNotNone(created_webhook.get('SUCCESS'),
|
||||
'failed to delete')
|
||||
self.assertEqual(self.pre_test_webhook_count, len(webhooks),
|
||||
'No webhooks should exist after deletion')
|
||||
|
||||
def test_delete_non_existing_webhook(self):
|
||||
self.assertRaises(ClientException,
|
||||
TempestClients.vitrage().webhook.delete,
|
||||
('non existant'))
|
||||
|
||||
def test_list_webhook(self):
|
||||
|
||||
webhooks = TempestClients.vitrage().webhook.list()
|
||||
self.assertEqual(self.pre_test_webhook_count,
|
||||
len(webhooks),
|
||||
'Amount of webhooks should be the same as '
|
||||
'before the test')
|
||||
|
||||
created_webhook = TempestClients.vitrage().webhook.add(
|
||||
url="https://www.test.com",
|
||||
regex_filter=REGEX_PROPS,
|
||||
headers=HEADERS_PROPS
|
||||
)
|
||||
|
||||
webhooks = TempestClients.vitrage().webhook.list()
|
||||
self.assertEqual(self.pre_test_webhook_count + 1, len(webhooks))
|
||||
self.assertEqual(created_webhook[HEADERS], webhooks[0][HEADERS])
|
||||
self.assertEqual(created_webhook['id'], webhooks[0]['id'])
|
||||
self.assertEqual(created_webhook[REGEX_FILTER],
|
||||
webhooks[0][REGEX_FILTER])
|
||||
|
||||
TempestClients.vitrage().webhook.delete(
|
||||
created_webhook['id'])
|
||||
|
||||
def test_show_webhook(self):
|
||||
webhooks = TempestClients.vitrage().webhook.list()
|
||||
self.assertEqual(self.pre_test_webhook_count,
|
||||
len(webhooks),
|
||||
'Amount of webhooks should be the same as '
|
||||
'before the test')
|
||||
|
||||
created_webhook = TempestClients.vitrage().webhook.add(
|
||||
url="https://www.test.com",
|
||||
regex_filter=REGEX_PROPS,
|
||||
headers=HEADERS_PROPS
|
||||
)
|
||||
|
||||
show_webhook = TempestClients.vitrage().webhook.show(
|
||||
created_webhook['id']
|
||||
)
|
||||
|
||||
self.assertIsNotNone(show_webhook, 'webhook not listed')
|
||||
self.assertEqual(created_webhook[HEADERS],
|
||||
show_webhook[HEADERS],
|
||||
'headers mismatch')
|
||||
self.assertEqual(created_webhook[REGEX_FILTER],
|
||||
show_webhook[REGEX_FILTER],
|
||||
'regex mismatch')
|
||||
self.assertEqual(created_webhook[URL],
|
||||
show_webhook[URL],
|
||||
'URL mismatch')
|
||||
|
||||
TempestClients.vitrage().webhook.delete(
|
||||
created_webhook['id'])
|
268
vitrage_tempest_tests/tests/e2e/test_e2e_webhook.py
Normal file
268
vitrage_tempest_tests/tests/e2e/test_e2e_webhook.py
Normal file
@ -0,0 +1,268 @@
|
||||
# Copyright 2017 - Nokia
|
||||
#
|
||||
# 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_log import log as logging
|
||||
import requests
|
||||
from six.moves import BaseHTTPServer
|
||||
import socket
|
||||
from threading import Thread
|
||||
|
||||
from vitrage.common.constants import VertexProperties as VProps
|
||||
from vitrage_tempest_tests.tests.common.tempest_clients import TempestClients
|
||||
from vitrage_tempest_tests.tests.e2e.test_actions_base import TestActionsBase
|
||||
from vitrage_tempest_tests.tests import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
TRIGGER_ALARM_1 = 'e2e.test_webhook.alarm1'
|
||||
TRIGGER_ALARM_2 = 'e2e.test_webhook.alarm2'
|
||||
TRIGGER_ALARM_WITH_DEDUCED = 'e2e.test_webhook.alarm_with_deduced'
|
||||
URL = 'url'
|
||||
REGEX_FILTER = 'regex_filter'
|
||||
HEADERS = 'headers'
|
||||
HEADERS_PROPS = '{"content": "application/json"}'
|
||||
NAME_FILTER = '{"name": "e2e.*"}'
|
||||
NAME_FILTER_FOR_DEDUCED = '{"name": "e2e.test_webhook.deduced"}'
|
||||
TYPE_FILTER = '{"vitrage_type": "doctor"}'
|
||||
FILTER_NO_MATCH = '{"name": "NO MATCH"}'
|
||||
|
||||
|
||||
class TestWebhook(TestActionsBase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super(TestWebhook, cls).setUpClass()
|
||||
# Configure mock server.
|
||||
cls.mock_server_port = _get_free_port()
|
||||
cls.mock_server = MockHTTPServer(('localhost', cls.mock_server_port),
|
||||
MockServerRequestHandler)
|
||||
|
||||
# Start running mock server in a separate thread.
|
||||
cls.mock_server_thread = Thread(target=cls.mock_server.serve_forever)
|
||||
cls.mock_server_thread.setDaemon(True)
|
||||
cls.mock_server_thread.start()
|
||||
cls.URL_PROPS = 'http://localhost:%s/' % cls.mock_server_port
|
||||
|
||||
@utils.tempest_logger
|
||||
def test_webhook_basic_event(self):
|
||||
|
||||
try:
|
||||
|
||||
# Add webhook with filter matching alarm
|
||||
TempestClients.vitrage().webhook.add(
|
||||
url=self.URL_PROPS,
|
||||
regex_filter=NAME_FILTER,
|
||||
headers=HEADERS_PROPS
|
||||
)
|
||||
|
||||
# Raise alarm
|
||||
self._trigger_do_action(TRIGGER_ALARM_1)
|
||||
|
||||
# Check event received
|
||||
self.assertEqual(1, len(self.mock_server.requests),
|
||||
'Wrong number of notifications for raise alarm')
|
||||
|
||||
# Undo
|
||||
self._trigger_undo_action(TRIGGER_ALARM_1)
|
||||
|
||||
# Check event undo received
|
||||
self.assertEqual(2, len(self.mock_server.requests),
|
||||
'Wrong number of notifications for clear alarm')
|
||||
|
||||
finally:
|
||||
self._delete_webhooks()
|
||||
self._trigger_undo_action(TRIGGER_ALARM_1)
|
||||
self.mock_server.reset_requests_list()
|
||||
|
||||
def test_webhook_with_no_filter(self):
|
||||
"""Test to see that a webhook with no filter receives all
|
||||
|
||||
notifications
|
||||
"""
|
||||
|
||||
try:
|
||||
|
||||
# Add webhook
|
||||
TempestClients.vitrage().webhook.add(
|
||||
url=self.URL_PROPS,
|
||||
regex_filter=NAME_FILTER,
|
||||
)
|
||||
|
||||
# Raise alarm
|
||||
self._trigger_do_action(TRIGGER_ALARM_1)
|
||||
|
||||
# Check event received
|
||||
self.assertEqual(1, len(self.mock_server.requests),
|
||||
'Wrong number of notifications for raise alarm')
|
||||
|
||||
# Raise another alarm
|
||||
self._trigger_do_action(TRIGGER_ALARM_2)
|
||||
|
||||
# Check second event received
|
||||
self.assertEqual(2, len(self.mock_server.requests),
|
||||
'Wrong number of notifications for clear alarm')
|
||||
|
||||
finally:
|
||||
self._delete_webhooks()
|
||||
self._trigger_undo_action(TRIGGER_ALARM_1)
|
||||
self._trigger_undo_action(TRIGGER_ALARM_2)
|
||||
self.mock_server.reset_requests_list()
|
||||
|
||||
def test_webhook_with_no_match(self):
|
||||
"""Test to check that filters with no match do not send event """
|
||||
|
||||
try:
|
||||
|
||||
# Add webhook
|
||||
TempestClients.vitrage().webhook.add(
|
||||
url=self.URL_PROPS,
|
||||
regex_filter=FILTER_NO_MATCH,
|
||||
)
|
||||
|
||||
# Raise alarm
|
||||
self._trigger_do_action(TRIGGER_ALARM_1)
|
||||
|
||||
# Check event not received
|
||||
self.assertEqual(0, len(self.mock_server.requests),
|
||||
'event should not have passed filter')
|
||||
|
||||
# Raise another alarm
|
||||
self._trigger_do_action(TRIGGER_ALARM_2)
|
||||
|
||||
# Check second event not received
|
||||
self.assertEqual(0, len(self.mock_server.requests),
|
||||
'event should not have passed filter')
|
||||
|
||||
finally:
|
||||
self._delete_webhooks()
|
||||
self._trigger_undo_action(TRIGGER_ALARM_1)
|
||||
self._trigger_undo_action(TRIGGER_ALARM_2)
|
||||
self.mock_server.reset_requests_list()
|
||||
|
||||
def test_multiple_webhooks(self):
|
||||
"""Test to check filter by type and by ID (with 2 different
|
||||
|
||||
webhooks)
|
||||
"""
|
||||
|
||||
host_id = self.orig_host[VProps.VITRAGE_ID]
|
||||
ID_FILTER = '{"%s": "%s"}' % (VProps.VITRAGE_RESOURCE_ID, host_id)
|
||||
|
||||
try:
|
||||
|
||||
# Add webhook
|
||||
TempestClients.vitrage().webhook.add(
|
||||
url=self.URL_PROPS,
|
||||
regex_filter=TYPE_FILTER,
|
||||
)
|
||||
|
||||
TempestClients.vitrage().webhook.add(
|
||||
url=self.URL_PROPS,
|
||||
regex_filter=ID_FILTER,
|
||||
)
|
||||
|
||||
# Raise alarm
|
||||
self._trigger_do_action(TRIGGER_ALARM_1)
|
||||
|
||||
# Check event received
|
||||
self.assertEqual(2, len(self.mock_server.requests),
|
||||
'event not posted to all webhooks')
|
||||
|
||||
# Raise another alarm
|
||||
self._trigger_do_action(TRIGGER_ALARM_2)
|
||||
|
||||
# Check second event received
|
||||
self.assertEqual(4, len(self.mock_server.requests),
|
||||
'event not posted to all webhooks')
|
||||
|
||||
finally:
|
||||
self._delete_webhooks()
|
||||
self._trigger_undo_action(TRIGGER_ALARM_1)
|
||||
self._trigger_undo_action(TRIGGER_ALARM_2)
|
||||
self.mock_server.reset_requests_list()
|
||||
|
||||
# Will be un-commented-out in the next change
|
||||
#
|
||||
# @utils.tempest_logger
|
||||
# def test_webhook_for_deduced_alarm(self):
|
||||
#
|
||||
# try:
|
||||
#
|
||||
# # Add webhook with filter for the deduced alarm
|
||||
# TempestClients.vitrage().webhook.add(
|
||||
# url=self.URL_PROPS,
|
||||
# regex_filter=NAME_FILTER_FOR_DEDUCED,
|
||||
# headers=HEADERS_PROPS
|
||||
# )
|
||||
#
|
||||
# # Raise the trigger alarm
|
||||
# self._trigger_do_action(TRIGGER_ALARM_WITH_DEDUCED)
|
||||
#
|
||||
# # Check event received - expected one for the deduced alarm
|
||||
# # (the trigger alarm does not pass the filter). This test verifies
|
||||
# # that the webhook is called only once for the deduced alarm.
|
||||
# self.assertEqual(1, len(self.mock_server.requests),
|
||||
# 'Wrong number of notifications for deduced alarm')
|
||||
#
|
||||
# # Undo
|
||||
# self._trigger_undo_action(TRIGGER_ALARM_WITH_DEDUCED)
|
||||
#
|
||||
# # Check event undo received
|
||||
# self.assertEqual(2, len(self.mock_server.requests),
|
||||
# 'Wrong number of notifications for clear deduced '
|
||||
# 'alarm')
|
||||
#
|
||||
# finally:
|
||||
# self._delete_webhooks()
|
||||
# self._trigger_undo_action(TRIGGER_ALARM_WITH_DEDUCED)
|
||||
# self.mock_server.reset_requests_list()
|
||||
|
||||
def _delete_webhooks(self):
|
||||
webhooks = TempestClients.vitrage().webhook.list()
|
||||
for webhook in webhooks:
|
||||
TempestClients.vitrage().webhook.delete(webhook['id'])
|
||||
|
||||
|
||||
def _get_free_port():
|
||||
s = socket.socket(socket.AF_INET, type=socket.SOCK_STREAM)
|
||||
s.bind(('localhost', 0))
|
||||
address, port = s.getsockname()
|
||||
s.close()
|
||||
return port
|
||||
|
||||
|
||||
class MockHTTPServer(BaseHTTPServer.HTTPServer):
|
||||
|
||||
def __init__(self, server, handler):
|
||||
BaseHTTPServer.HTTPServer.__init__(self, server, handler)
|
||||
self.requests = []
|
||||
|
||||
def process_request(self, request, client_address):
|
||||
self.requests.append(request)
|
||||
LOG.info('received request: %s', str(request))
|
||||
BaseHTTPServer.HTTPServer.process_request(
|
||||
self, client_address=client_address, request=request)
|
||||
|
||||
def reset_requests_list(self):
|
||||
self.requests = []
|
||||
|
||||
|
||||
class MockServerRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
|
||||
def do_POST(self):
|
||||
|
||||
# Process a HTTP Post request and return status code 200
|
||||
self.send_response(requests.codes.ok)
|
||||
self.end_headers()
|
||||
return
|
@ -0,0 +1,29 @@
|
||||
metadata:
|
||||
name: e2e_webhook
|
||||
definitions:
|
||||
entities:
|
||||
- entity:
|
||||
category: ALARM
|
||||
name: e2e.test_webhook.alarm_with_deduced
|
||||
template_id: host_alarm
|
||||
- entity:
|
||||
category: RESOURCE
|
||||
type: nova.host
|
||||
template_id: host
|
||||
relationships:
|
||||
- relationship:
|
||||
source: host_alarm
|
||||
target: host
|
||||
relationship_type: on
|
||||
template_id : alarm_on_host
|
||||
scenarios:
|
||||
- scenario:
|
||||
condition: alarm_on_host
|
||||
actions:
|
||||
- action:
|
||||
action_type: raise_alarm
|
||||
action_target:
|
||||
target: host
|
||||
properties:
|
||||
alarm_name: e2e.test_webhook.deduced
|
||||
severity: WARNING
|
Loading…
x
Reference in New Issue
Block a user