Working on Data Flow (step 2)
* Added ExpressionEvaluator interface and YAQL implementation * Removed yaql_utils, evaluator is now a more flexible replacement * Fixed the places where yaql_utils was used * Adjusted test cases Change-Id: I7de70e678c211df34788763047b8361de0d3902a
This commit is contained in:
parent
58407b6f94
commit
b3c23b7e1b
@ -64,7 +64,7 @@ def get_rest_action(task):
|
||||
|
||||
# input_yaql = task.get('input')
|
||||
# TODO(nmakhotkin) extract input from context within the YAQL expression
|
||||
task_input = {} # yaql_utils.evaluate(input_yaql, ctx)
|
||||
task_input = {} # expressions.evaluate(input_expr, ctx)
|
||||
task_data = {}
|
||||
|
||||
if method.upper() == "GET":
|
||||
|
@ -17,7 +17,7 @@
|
||||
from mistral.engine.actions import action_types as a_t
|
||||
from mistral import exceptions as exc
|
||||
from mistral.engine import states
|
||||
from mistral.utils import yaql_utils
|
||||
from mistral.engine import expressions as expr
|
||||
|
||||
|
||||
def get_action_type(task):
|
||||
@ -30,16 +30,17 @@ def is_task_synchronous(task):
|
||||
|
||||
def extract_state_result(action, action_result):
|
||||
# All non-Mistral tasks are sync-auto because service doesn't know
|
||||
# about Mistral and we need to receive the result immediately
|
||||
# about Mistral and we need to receive the result immediately.
|
||||
if action.type != a_t.MISTRAL_REST_API:
|
||||
if action.result_helper.get('select'):
|
||||
result = yaql_utils.evaluate(action.result_helper['select'],
|
||||
result = expr.evaluate(action.result_helper['select'],
|
||||
action_result)
|
||||
# TODO(nmakhotkin) get state for other actions
|
||||
state = states.get_state_by_http_status_code(action.status)
|
||||
else:
|
||||
raise exc.InvalidActionException("Cannot get the result of sync "
|
||||
"task without YAQL expression")
|
||||
|
||||
return state, result
|
||||
raise exc.InvalidActionException("Error. Wrong type of action to "
|
||||
"retrieve the result")
|
||||
|
57
mistral/engine/expressions.py
Normal file
57
mistral/engine/expressions.py
Normal file
@ -0,0 +1,57 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2013 - Mirantis, Inc.
|
||||
#
|
||||
# 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 abc
|
||||
import yaql
|
||||
|
||||
from mistral.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Evaluator(object):
|
||||
"""Expression evaluator interface.
|
||||
|
||||
Having this interface gives the flexibility to change the actual expression
|
||||
language used in Mistral DSL for conditions, output calculation etc.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
@abc.abstractmethod
|
||||
def evaluate(cls, expression, context):
|
||||
"""Evaluates the expression against the given data context.
|
||||
|
||||
:param expression: Expression string
|
||||
:param context: Data context
|
||||
:return: Expression result
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class YAQLEvaluator(Evaluator):
|
||||
@classmethod
|
||||
def evaluate(cls, expression, context):
|
||||
LOG.debug("Evaluating YAQL expression [expression='%s', context=%s]")
|
||||
|
||||
return yaql.parse(expression).evaluate(context)
|
||||
|
||||
|
||||
# TODO(rakhmerov): Make it configurable.
|
||||
_EVALUATOR = YAQLEvaluator()
|
||||
|
||||
|
||||
def evaluate(expression, context):
|
||||
_EVALUATOR.evaluate(expression, context)
|
@ -16,7 +16,7 @@
|
||||
|
||||
import unittest2
|
||||
|
||||
from mistral.utils import yaql_utils
|
||||
from mistral.engine import expressions as expr
|
||||
|
||||
|
||||
DATA = {
|
||||
@ -44,33 +44,37 @@ SERVERS = {
|
||||
}
|
||||
|
||||
|
||||
class YaqlTest(unittest2.TestCase):
|
||||
class YaqlEvaluatorTest(unittest2.TestCase):
|
||||
def setUp(self):
|
||||
super(YaqlEvaluatorTest, self).setUp()
|
||||
self._evaluator = expr.YAQLEvaluator()
|
||||
|
||||
def test_expression_result(self):
|
||||
res = yaql_utils.evaluate("$.server", DATA)
|
||||
res = self._evaluator.evaluate('$.server', DATA)
|
||||
self.assertEqual(res, {
|
||||
"id": "03ea824a-aa24-4105-9131-66c48ae54acf",
|
||||
"name": "cloud-fedora",
|
||||
"status": "ACTIVE"
|
||||
'id': "03ea824a-aa24-4105-9131-66c48ae54acf",
|
||||
'name': 'cloud-fedora',
|
||||
'status': 'ACTIVE'
|
||||
})
|
||||
|
||||
res = yaql_utils.evaluate("$.server.id", DATA)
|
||||
self.assertEqual(res, "03ea824a-aa24-4105-9131-66c48ae54acf")
|
||||
res = self._evaluator.evaluate('$.server.id', DATA)
|
||||
self.assertEqual(res, '03ea824a-aa24-4105-9131-66c48ae54acf')
|
||||
|
||||
res = yaql_utils.evaluate("$.server.status = 'ACTIVE'", DATA)
|
||||
res = self._evaluator.evaluate("$.server.status = 'ACTIVE'", DATA)
|
||||
self.assertTrue(res)
|
||||
|
||||
def test_wrong_expression(self):
|
||||
res = yaql_utils.evaluate("$.status = 'Invalid value'", DATA)
|
||||
res = self._evaluator.evaluate("$.status = 'Invalid value'", DATA)
|
||||
self.assertFalse(res)
|
||||
|
||||
res = yaql_utils.evaluate("$.wrong_key", DATA)
|
||||
res = self._evaluator.evaluate('$.wrong_key', DATA)
|
||||
self.assertIsNone(res)
|
||||
|
||||
expression_str = "invalid_expression_string"
|
||||
res = yaql_utils.evaluate(expression_str, DATA)
|
||||
expression_str = 'invalid_expression_string'
|
||||
res = self._evaluator.evaluate(expression_str, DATA)
|
||||
self.assertEqual(res, expression_str)
|
||||
|
||||
def test_select_result(self):
|
||||
res = yaql_utils.evaluate("$.servers[$.name = ubuntu]", SERVERS)
|
||||
res = self._evaluator.evaluate('$.servers[$.name = ubuntu]', SERVERS)
|
||||
item = list(res)[0]
|
||||
self.assertEqual(item, {'name': 'ubuntu'})
|
@ -1,21 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2013 - Mirantis, Inc.
|
||||
#
|
||||
# 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 yaql
|
||||
|
||||
|
||||
def evaluate(expression_str, data):
|
||||
return yaql.parse(expression_str).evaluate(data)
|
Loading…
Reference in New Issue
Block a user