diff --git a/devstack/plugin.sh b/devstack/plugin.sh index 859a25b07..9b8389919 100755 --- a/devstack/plugin.sh +++ b/devstack/plugin.sh @@ -143,11 +143,12 @@ function install_mistral_pythonclient { # start_mistral - Start running processes, including screen function start_mistral { - if is_service_enabled mistral-api && is_service_enabled mistral-engine && is_service_enabled mistral-executor ; then + if is_service_enabled mistral-api && is_service_enabled mistral-engine && is_service_enabled mistral-executor && is_service_enabled mistral-event-engine ; then echo_summary "Installing all mistral services in separate processes" run_process mistral-api "$MISTRAL_BIN_DIR/mistral-server --server api --config-file $MISTRAL_CONF_DIR/mistral.conf" run_process mistral-engine "$MISTRAL_BIN_DIR/mistral-server --server engine --config-file $MISTRAL_CONF_DIR/mistral.conf" run_process mistral-executor "$MISTRAL_BIN_DIR/mistral-server --server executor --config-file $MISTRAL_CONF_DIR/mistral.conf" + run_process mistral-event-engine "$MISTRAL_BIN_DIR/mistral-server --server event-engine --config-file $MISTRAL_CONF_DIR/mistral.conf" else echo_summary "Installing all mistral services in one process" run_process mistral "$MISTRAL_BIN_DIR/mistral-server --server all --config-file $MISTRAL_CONF_DIR/mistral.conf" @@ -158,7 +159,7 @@ function start_mistral { # stop_mistral - Stop running processes function stop_mistral { # Kill the Mistral screen windows - for serv in mistral mistral-api mistral-engine mistral-executor; do + for serv in mistral mistral-api mistral-engine mistral-executor mistral-event-engine; do stop_process $serv done } diff --git a/devstack/settings b/devstack/settings index ddeb3109a..9cddc9e33 100644 --- a/devstack/settings +++ b/devstack/settings @@ -10,7 +10,7 @@ # is an incorrect way to run services and all services by default will run in one screen -enable_service mistral mistral-api mistral-engine mistral-executor +enable_service mistral mistral-api mistral-engine mistral-executor mistral-event-engine # Set up default repos diff --git a/mistral_tempest_tests/services/base.py b/mistral_tempest_tests/services/base.py index a4e91dccd..8da3928cf 100644 --- a/mistral_tempest_tests/services/base.py +++ b/mistral_tempest_tests/services/base.py @@ -71,6 +71,7 @@ class MistralClientBase(rest_client.RestClient): self.triggers = [] self.actions = [] self.action_executions = [] + self.event_triggers = [] def get_list_obj(self, name): resp, body = self.get(name) diff --git a/mistral_tempest_tests/services/v2/mistral_client.py b/mistral_tempest_tests/services/v2/mistral_client.py index eeb4fbff4..207eff368 100644 --- a/mistral_tempest_tests/services/v2/mistral_client.py +++ b/mistral_tempest_tests/services/v2/mistral_client.py @@ -139,3 +139,26 @@ class MistralClientV2(base.MistralClientBase): self.action_executions.append(json.loads(body)['id']) return resp, json.loads(body) + + def create_event_trigger(self, wf_id, exchange, topic, event, name='', + wf_input=None, wf_params=None): + post_body = { + 'workflow_id': wf_id, + 'exchange': exchange, + 'topic': topic, + 'event': event, + 'name': name + } + + if wf_input: + post_body.update({'workflow_input': json.dumps(wf_input)}) + + if wf_params: + post_body.update({'workflow_params': json.dumps(wf_params)}) + + rest, body = self.post('event_triggers', json.dumps(post_body)) + + event_trigger = json.loads(body) + self.event_triggers.append(event_trigger['id']) + + return rest, event_trigger diff --git a/mistral_tempest_tests/tests/api/v2/test_event_triggers.py b/mistral_tempest_tests/tests/api/v2/test_event_triggers.py new file mode 100644 index 000000000..c2dbac363 --- /dev/null +++ b/mistral_tempest_tests/tests/api/v2/test_event_triggers.py @@ -0,0 +1,109 @@ +# Copyright 2016 Catalyst IT 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 exceptions +from tempest import test + +from mistral_tempest_tests.tests import base + +EXCHANGE = 'openstack' +EVENT_ENGINE_TOPIC = 'mistral_event_engine' +EVENT = 'fake.event' + + +class EventTriggerTestsV2(base.TestCase): + """Test class for event engine function. + + NOTE: This test class doesn't fully test event engine functions, because + we can not send real notifications to the internal message queue to + trigger the specified workflows. + + So, before notification is supported in Mistral, we can only test the API + functions. + """ + + _service = 'workflowv2' + + def setUp(self): + super(EventTriggerTestsV2, self).setUp() + _, body = self.client.create_workflow('wf_v2.yaml') + self.wf_id = body['workflows'][0]['id'] + + def tearDown(self): + for tr in self.client.event_triggers: + self.client.delete_obj('event_triggers', tr) + self.client.event_triggers = [] + + for wf in self.client.workflows: + self.client.delete_obj('workflows', wf) + self.client.workflows = [] + + super(EventTriggerTestsV2, self).tearDown() + + @test.attr(type='sanity') + def test_create_get_delete_event_trigger(self): + name = 'my_event_trigger' + + resp, body = self.client.create_event_trigger( + self.wf_id, EXCHANGE, EVENT_ENGINE_TOPIC, EVENT, name) + + trigger_id = body['id'] + + self.assertEqual(201, resp.status) + self.assertEqual(name, body['name']) + + resp, body = self.client.get_list_obj('event_triggers') + self.assertEqual(200, resp.status) + + trs_names = [tr['name'] for tr in body['event_triggers']] + self.assertIn(name, trs_names) + + self.client.delete_obj('event_triggers', trigger_id) + self.client.event_triggers.remove(trigger_id) + + _, body = self.client.get_list_obj('event_triggers') + + trs_names = [tr['name'] for tr in body['event_triggers']] + self.assertNotIn(name, trs_names) + + @test.attr(type='negative') + def test_create_event_trigger_without_necessary_param(self): + self.assertRaises(exceptions.BadRequest, + self.client.create_event_trigger, + self.wf_id, EXCHANGE, EVENT_ENGINE_TOPIC, '') + + @test.attr(type='negative') + def test_create_event_trigger_with_nonexist_wf(self): + self.assertRaises(exceptions.BadRequest, + self.client.create_event_trigger, + 'nonexist', EXCHANGE, EVENT_ENGINE_TOPIC, EVENT) + + @test.attr(type='negative') + def test_create_event_trigger_duplicate(self): + name = 'my_event_trigger' + + self.client.create_event_trigger( + self.wf_id, EXCHANGE, EVENT_ENGINE_TOPIC, EVENT, name) + + self.assertRaises(exceptions.Conflict, + self.client.create_event_trigger, + self.wf_id, EXCHANGE, EVENT_ENGINE_TOPIC, EVENT) + + @test.attr(type='negative') + def test_get_nonexistent_event_trigger(self): + fake_id = '123e4567-e89b-12d3-a456-426655440000' + + self.assertRaises(exceptions.NotFound, + self.client.get_object, + 'event_triggers', fake_id) diff --git a/mistral_tempest_tests/tests/api/v2/test_workflows.py b/mistral_tempest_tests/tests/api/v2/test_workflows.py index 2b91e78b6..3d3a2efec 100644 --- a/mistral_tempest_tests/tests/api/v2/test_workflows.py +++ b/mistral_tempest_tests/tests/api/v2/test_workflows.py @@ -250,6 +250,25 @@ class WorkflowTestsV2(base.TestCase): self.client.delete_obj('cron_triggers', tr_name) self.client.triggers.remove(tr_name) + @test.attr(type='negative') + def test_delete_wf_with_event_trigger_associate(self): + _, body = self.client.create_workflow('wf_v2.yaml') + wf_id = body['workflows'][0]['id'] + resp, body = self.client.create_event_trigger( + wf_id, 'openstack', 'notification', 'fake.event') + self.assertEqual(201, resp.status) + + try: + self.assertRaises( + exceptions.BadRequest, + self.client.delete_obj, + 'workflows', + wf_id + ) + finally: + self.client.delete_obj('event_triggers', body['id']) + self.client.event_triggers.remove(body['id']) + @test.attr(type='negative') def test_delete_wf_with_trigger_associate_in_other_tenant(self): self.useFixture(lockutils.LockFixture('mistral-workflow'))