From 3d3b7a7820c2bf9b70dc788ee8fcbbe227bb18e5 Mon Sep 17 00:00:00 2001 From: Renat Akhmerov Date: Fri, 30 May 2014 17:04:44 +0700 Subject: [PATCH] Making "Namespaces" section truly optional * Added test on this case Closes-Bug: #1322737 Co-Authored-By: Nikolay Mahotkin Change-Id: I35398da5963db8b5d085baa82dc21a5df64ec153 --- mistral/engine/__init__.py | 7 +-- mistral/engine/drivers/default/executor.py | 1 - .../tests/unit/engine/default/test_engine.py | 34 +++++++++++++ mistral/tests/unit/workbook/test_workbook.py | 51 ++++++++++--------- mistral/workbook/workbook.py | 16 +++--- 5 files changed, 72 insertions(+), 37 deletions(-) diff --git a/mistral/engine/__init__.py b/mistral/engine/__init__.py index d891b9e34..7926d9fbd 100644 --- a/mistral/engine/__init__.py +++ b/mistral/engine/__init__.py @@ -302,12 +302,7 @@ class Engine(object): for task in task_list: state, task_runtime_context = retry.get_task_runtime(task) - action_ns = workbook.namespaces.get(task.get_action_namespace()) - - action_spec = None - if action_ns: - action_spec = \ - action_ns.actions.get(task.get_action_name()) + action_spec = workbook.get_action(task.get_full_action_name()) db_task = db_api.task_create(workbook_name, execution_id, { "name": task.name, diff --git a/mistral/engine/drivers/default/executor.py b/mistral/engine/drivers/default/executor.py index 907511187..ec58f0696 100644 --- a/mistral/engine/drivers/default/executor.py +++ b/mistral/engine/drivers/default/executor.py @@ -56,7 +56,6 @@ class DefaultExecutor(executor.Executor): else: try: action.run() - except exc.ActionException: self.engine.convey_task_result(task['workbook_name'], task['execution_id'], diff --git a/mistral/tests/unit/engine/default/test_engine.py b/mistral/tests/unit/engine/default/test_engine.py index 3e814caf8..8693a4667 100644 --- a/mistral/tests/unit/engine/default/test_engine.py +++ b/mistral/tests/unit/engine/default/test_engine.py @@ -17,6 +17,7 @@ import mock from oslo.config import cfg +from mistral import dsl_parser as parser from mistral.tests import base from mistral.openstack.common import log as logging from mistral.db import api as db_api @@ -39,6 +40,16 @@ cfg.CONF.set_default('auth_enable', False, group='pecan') #TODO(rakhmerov): add more tests for errors, execution stop etc. +WB_WITHOUT_NAMESPACES = """Workflow: + tasks: + task: + action: std.http + parameters: + method: GET + url: http://some_url +""" + + @mock.patch.object( engine.EngineClient, 'start_workflow_execution', mock.MagicMock(side_effect=base.EngineTestCase.mock_start_workflow)) @@ -277,3 +288,26 @@ class TestScalableEngine(base.EngineTestCase): self._assert_single_item(tasks, state=states.ERROR) self._assert_multiple_items(tasks, 5, state=states.SUCCESS) + + @mock.patch.object( + concrete_engine.DefaultEngine, "_notify_task_executors", + mock.MagicMock(return_value="")) + @mock.patch.object( + engine.Engine, '_get_workbook', + mock.MagicMock( + return_value=parser.get_workbook(WB_WITHOUT_NAMESPACES))) + @mock.patch.object( + concrete_engine.DefaultEngine, '_run_tasks', + mock.MagicMock(side_effect=base.EngineTestCase.mock_run_tasks)) + def test_engine_without_namespaces(self): + execution = self.engine.start_workflow_execution(WB_NAME, "task", {}) + + tasks = db_api.tasks_get(WB_NAME, execution['id']) + + self.assertIsNotNone(tasks) + self.assertEqual(1, len(tasks)) + self.assertEqual(tasks[0]['state'], states.SUCCESS) + + execution = db_api.execution_get(WB_NAME, execution['id']) + + self.assertEqual(execution['state'], states.SUCCESS) diff --git a/mistral/tests/unit/workbook/test_workbook.py b/mistral/tests/unit/workbook/test_workbook.py index 4da24db7c..19db36cc3 100644 --- a/mistral/tests/unit/workbook/test_workbook.py +++ b/mistral/tests/unit/workbook/test_workbook.py @@ -18,10 +18,12 @@ from mistral import dsl_parser as parser from mistral.tests import base -SIMPLE_WORKBOOK = """Workflow: +SIMPLE_WORKBOOK = """ +Workflow: tasks: create-vms: - action: MyRest.create-vm""" + action: MyRest.create-vm +""" class DSLModelTest(base.BaseTest): @@ -29,24 +31,22 @@ class DSLModelTest(base.BaseTest): self.doc = base.get_resource("test_rest.yaml") def test_load_dsl(self): - self.workbook = parser.get_workbook(self.doc) - self.assertEqual(self.workbook.workflow.tasks.items, - self.workbook.tasks.items) - self.assertEqual(self.workbook.tasks.get("create-vms").name, - "create-vms") - self.assertEqual(4, - len(self.workbook.namespaces.get("MyRest").actions)) + wb = parser.get_workbook(self.doc) + + self.assertEqual(wb.workflow.tasks.items, wb.tasks.items) + self.assertEqual(wb.tasks.get("create-vms").name, "create-vms") + self.assertEqual(4, len(wb.namespaces.get("MyRest").actions)) def test_tasks(self): - self.workbook = parser.get_workbook(self.doc) - self.assertEqual(len(self.workbook.tasks), 6) + wb = parser.get_workbook(self.doc) + self.assertEqual(len(wb.tasks), 6) - attach_volumes = self.workbook.tasks.get("attach-volumes") + attach_volumes = wb.tasks.get("attach-volumes") self.assertEqual(attach_volumes.get_action_namespace(), "MyRest") t_parameters = {"image_id": 1234, "flavor_id": 2} - create_vm_nova = self.workbook.tasks.get("create-vm-nova") + create_vm_nova = wb.tasks.get("create-vm-nova") self.assertEqual(create_vm_nova.parameters, t_parameters) @@ -54,7 +54,8 @@ class DSLModelTest(base.BaseTest): self.assertEqual(attach_volumes.requires, attach_requires) - subsequent = self.workbook.tasks.get("test_subsequent") + subsequent = wb.tasks.get("test_subsequent") + subseq_success = subsequent.get_on_success() subseq_error = subsequent.get_on_error() subseq_finish = subsequent.get_on_finish() @@ -65,9 +66,9 @@ class DSLModelTest(base.BaseTest): self.assertEqual(subseq_finish, {"create-vms": ''}) def test_actions(self): - self.workbook = parser.get_workbook(self.doc) + wb = parser.get_workbook(self.doc) - actions = self.workbook.namespaces.get("MyRest").actions + actions = wb.namespaces.get("MyRest").actions self.assertEqual(len(actions), 4) @@ -83,14 +84,18 @@ class DSLModelTest(base.BaseTest): self.assertEqual('application/json', base_params['headers']['Content-Type']) + action = wb.get_action("MyRest.create-vm") + + self.assertIsNotNone(action) + self.assertEqual("create-vm", action.name) + self.assertEqual("MyRest", action.namespace) + def test_namespaces(self): - self.workbook = parser.get_workbook(self.doc) + wb = parser.get_workbook(self.doc) - namespaces = self.workbook.namespaces + self.assertEqual(len(wb.namespaces), 2) - self.assertEqual(len(namespaces), 2) - - nova_namespace = namespaces.get("Nova") + nova_namespace = wb.namespaces.get("Nova") self.assertEqual(1, len(nova_namespace.actions)) @@ -98,6 +103,6 @@ class DSLModelTest(base.BaseTest): parser.get_workbook(SIMPLE_WORKBOOK) def test_triggers(self): - self.workbook = parser.get_workbook(self.doc) + wb = parser.get_workbook(self.doc) - self.assertEqual(len(self.workbook.get_triggers()), 1) + self.assertEqual(len(wb.get_triggers()), 1) diff --git a/mistral/workbook/workbook.py b/mistral/workbook/workbook.py index 9c94a963f..6f19f3f10 100644 --- a/mistral/workbook/workbook.py +++ b/mistral/workbook/workbook.py @@ -24,12 +24,14 @@ class WorkbookSpec(base.BaseSpec): def __init__(self, doc): super(WorkbookSpec, self).__init__(doc) - self.namespaces = None + self.namespaces = {} if self.validate(): ns_dict = self._data.get('Namespaces') + if ns_dict: self.namespaces = namespaces.NamespaceSpecList(ns_dict) + self.workflow = workflow.WorkflowSpec(self._data['Workflow']) self.tasks = self.workflow.tasks @@ -47,15 +49,15 @@ class WorkbookSpec(base.BaseSpec): return triggers - def get_action(self, task_action_name): - if task_action_name.find(":") == -1: + def get_action(self, full_action_name): + if full_action_name.find(".") == -1: return {} - namespace_name = task_action_name.split(':')[0] - action_name = task_action_name.split(':')[1] - action = self.namespaces.get(namespace_name).actions.get(action_name) + ns_name = full_action_name.split('.')[0] + action_name = full_action_name.split('.')[1] - return action + if self.namespaces: + return self.namespaces.get(ns_name).actions.get(action_name) def get_actions(self, namespace_name): return self.namespaces.get(namespace_name).actions