From 3202940f1a2cfb96c27c83acd304a60fe5888589 Mon Sep 17 00:00:00 2001 From: Nikolay Mahotkin Date: Mon, 12 Jan 2015 16:37:56 +0300 Subject: [PATCH] Add validation on 'with-items' input Partially implements blueprint mistral-with-items Change-Id: I5c2446133ab6447ffd8f9c6336b11cc8fb340804 --- mistral/exceptions.py | 4 ++ .../tests/unit/workflow/test_with_items.py | 40 ++++++++++++++++++- mistral/workflow/with_items.py | 19 +++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/mistral/exceptions.py b/mistral/exceptions.py index cdec7d054..ca20f88c2 100644 --- a/mistral/exceptions.py +++ b/mistral/exceptions.py @@ -89,6 +89,10 @@ class WorkflowInputException(MistralException): http_code = 400 +class InputException(MistralException): + http_code = 400 + + class ApplicationContextNotFoundException(MistralException): http_code = 400 message = "Application context not found" diff --git a/mistral/tests/unit/workflow/test_with_items.py b/mistral/tests/unit/workflow/test_with_items.py index 55174e0d3..175863c02 100644 --- a/mistral/tests/unit/workflow/test_with_items.py +++ b/mistral/tests/unit/workflow/test_with_items.py @@ -15,6 +15,7 @@ # limitations under the License. from mistral.db.v2.sqlalchemy import models +from mistral import exceptions as exc from mistral.tests import base from mistral.workbook.v2 import tasks from mistral.workflow import utils @@ -114,4 +115,41 @@ class WithItemsCalculationsTest(base.BaseTest): {'name_info': {'name': 'Mistral'}, 'server_info': 'server3'}, ], action_input_collection - ) \ No newline at end of file + ) + + def test_calculate_input_wrong_array_length(self): + with_items_input = { + 'name_info': [ + {'name': 'John'}, + {'name': 'Ivan'}, + {'name': 'Mistral'} + ], + 'server_info': [ + 'server1', + 'server2' + ] + } + exception = self.assertRaises( + exc.InputException, + with_items.calc_input, + with_items_input + ) + + self.assertIn("the same length", exception.message) + + def test_calculate_input_not_list(self): + with_items_input = { + 'name_info': [ + {'name': 'John'}, + {'name': 'Ivan'}, + {'name': 'Mistral'} + ], + 'server_info': 'some_string' + } + exception = self.assertRaises( + exc.InputException, + with_items.calc_input, + with_items_input + ) + + self.assertIn("List type", exception.message) diff --git a/mistral/workflow/with_items.py b/mistral/workflow/with_items.py index 341d85d7b..10e74bc01 100644 --- a/mistral/workflow/with_items.py +++ b/mistral/workflow/with_items.py @@ -14,6 +14,7 @@ import copy +from mistral import exceptions as exc from mistral import expressions as expr @@ -112,6 +113,8 @@ def calc_input(with_items_input): :param with_items_input: Dict containing mapped variables to their arrays. :return: list containing dicts of each action input. """ + validate_input(with_items_input) + action_input_collection = [] for key, value in with_items_input.items(): @@ -126,6 +129,22 @@ def calc_input(with_items_input): return action_input_collection +def validate_input(with_items_input): + # Take only mapped values and check them. + values = with_items_input.values() + + if not all([isinstance(v, list) for v in values]): + raise exc.InputException( + "Wrong input format for: %s. List type is" + " expected for each value." % with_items_input) + + required_len = len(values[0]) + if not all(len(v) == required_len for v in values): + raise exc.InputException( + "Wrong input format for: %s. All arrays must" + " have the same length." % with_items_input) + + def _get_output_key(task_spec): return (task_spec.get_publish().keys()[0] if task_spec.get_publish() else None)