Merge "Allow any data to be passed to yaql function"
This commit is contained in:
commit
305e3b54b6
|
@ -853,8 +853,7 @@ class Yaql(function.Function):
|
|||
|
||||
def __init__(self, stack, fn_name, args):
|
||||
super(Yaql, self).__init__(stack, fn_name, args)
|
||||
self.parser = self.get_yaql_parser()
|
||||
self.context = yaql.create_context()
|
||||
self._yaql_context = yaql.create_context()
|
||||
|
||||
if not isinstance(self.args, collections.Mapping):
|
||||
raise TypeError(_('Arguments to "%s" must be a map.') %
|
||||
|
@ -863,9 +862,8 @@ class Yaql(function.Function):
|
|||
try:
|
||||
self._expression = self.args['expression']
|
||||
self._data = self.args.get('data', {})
|
||||
for arg in six.iterkeys(self.args):
|
||||
if arg not in ['expression', 'data']:
|
||||
raise KeyError
|
||||
if set(self.args) - set(['expression', 'data']):
|
||||
raise KeyError
|
||||
except (KeyError, TypeError):
|
||||
example = ('''%s:
|
||||
expression: $.data.var1.sum()
|
||||
|
@ -873,37 +871,25 @@ class Yaql(function.Function):
|
|||
var1: [3, 2, 1]''') % self.fn_name
|
||||
raise KeyError(_('"%(name)s" syntax should be %(example)s') % {
|
||||
'name': self.fn_name, 'example': example})
|
||||
self.validate_args()
|
||||
|
||||
def validate_expression(self, expression):
|
||||
if not isinstance(self._expression, function.Function):
|
||||
self._parse(self._expression)
|
||||
|
||||
def _parse(self, expression):
|
||||
if not isinstance(expression, six.string_types):
|
||||
raise TypeError(_('The "expression" argument to %s must '
|
||||
'contain a string.') % self.fn_name)
|
||||
|
||||
parse = self.get_yaql_parser()
|
||||
try:
|
||||
self.parser(expression)
|
||||
return parse(expression)
|
||||
except exceptions.YaqlException as yex:
|
||||
raise ValueError(_('Bad expression %s.') % yex)
|
||||
|
||||
def validate_args(self):
|
||||
if not isinstance(self._data,
|
||||
(collections.Mapping, function.Function)):
|
||||
raise TypeError(_('The "data" argument to "%s" must contain '
|
||||
'a map.') % self.fn_name)
|
||||
if not isinstance(self._expression,
|
||||
(six.string_types, function.Function)):
|
||||
raise TypeError(_('The "expression" argument to %s must '
|
||||
'contain a string or a '
|
||||
'function.') % self.fn_name)
|
||||
if isinstance(self._expression, six.string_types):
|
||||
self.validate_expression(self._expression)
|
||||
|
||||
def result(self):
|
||||
statement = self._parse(function.resolve(self._expression))
|
||||
data = function.resolve(self._data)
|
||||
if not isinstance(data, collections.Mapping):
|
||||
raise TypeError(_('The "data" argument to "%s" must contain '
|
||||
'a map.') % self.fn_name)
|
||||
if not isinstance(self._expression, six.string_types):
|
||||
self._expression = function.resolve(self._expression)
|
||||
self.validate_expression(self._expression)
|
||||
return self.parser(self._expression).evaluate({'data': data},
|
||||
self.context)
|
||||
return statement.evaluate({'data': data}, self._yaql_context)
|
||||
|
||||
|
||||
class Equals(function.Function):
|
||||
|
|
|
@ -1028,24 +1028,43 @@ class HOTemplateTest(common.HeatTestCase):
|
|||
|
||||
def test_yaql(self):
|
||||
snippet = {'yaql': {'expression': '$.data.var1.sum()',
|
||||
'data': {'var1': [1, 2, 3, 4]}}}
|
||||
'data': {'var1': [1, 2, 3, 4]}}}
|
||||
tmpl = template.Template(hot_newton_tpl_empty)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack', tmpl)
|
||||
resolved = self.resolve(snippet, tmpl, stack=stack)
|
||||
|
||||
self.assertEqual(10, resolved)
|
||||
|
||||
def test_yaql_invalid_data(self):
|
||||
snippet = {'yaql': {'expression': '$.data.var1.sum()',
|
||||
'data': 'mustbeamap'}}
|
||||
def test_yaql_list_input(self):
|
||||
snippet = {'yaql': {'expression': '$.data.sum()',
|
||||
'data': [1, 2, 3, 4]}}
|
||||
tmpl = template.Template(hot_newton_tpl_empty)
|
||||
msg = '.yaql: The "data" argument to "yaql" must contain a map.'
|
||||
self.assertRaisesRegexp(exception.StackValidationFailed,
|
||||
msg, self.resolve, snippet, tmpl)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack', tmpl)
|
||||
resolved = self.resolve(snippet, tmpl, stack=stack)
|
||||
|
||||
self.assertEqual(10, resolved)
|
||||
|
||||
def test_yaql_string_input(self):
|
||||
snippet = {'yaql': {'expression': '$.data',
|
||||
'data': 'whynotastring'}}
|
||||
tmpl = template.Template(hot_newton_tpl_empty)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack', tmpl)
|
||||
resolved = self.resolve(snippet, tmpl, stack=stack)
|
||||
|
||||
self.assertEqual('whynotastring', resolved)
|
||||
|
||||
def test_yaql_int_input(self):
|
||||
snippet = {'yaql': {'expression': '$.data + 2',
|
||||
'data': 2}}
|
||||
tmpl = template.Template(hot_newton_tpl_empty)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack', tmpl)
|
||||
resolved = self.resolve(snippet, tmpl, stack=stack)
|
||||
|
||||
self.assertEqual(4, resolved)
|
||||
|
||||
def test_yaql_bogus_keys(self):
|
||||
snippet = {'yaql': {'expression': '1 + 3',
|
||||
'data': 'mustbeamap',
|
||||
'data': {'var1': [1, 2, 3, 4]},
|
||||
'bogus': ""}}
|
||||
tmpl = template.Template(hot_newton_tpl_empty)
|
||||
self.assertRaises(exception.StackValidationFailed,
|
||||
|
@ -1053,7 +1072,7 @@ class HOTemplateTest(common.HeatTestCase):
|
|||
|
||||
def test_yaql_invalid_syntax(self):
|
||||
snippet = {'yaql': {'wrong': 'wrong_expr',
|
||||
'wrong_data': 'mustbeamap'}}
|
||||
'wrong_data': 'mustbeamap'}}
|
||||
tmpl = template.Template(hot_newton_tpl_empty)
|
||||
self.assertRaises(exception.StackValidationFailed,
|
||||
self.resolve, snippet, tmpl)
|
||||
|
@ -1074,10 +1093,7 @@ class HOTemplateTest(common.HeatTestCase):
|
|||
|
||||
def test_yaql_data_as_function(self):
|
||||
snippet = {'yaql': {'expression': '$.data.var1.len()',
|
||||
'data': {
|
||||
'var1': {'list_join': ['', ['1', '2']]}
|
||||
}
|
||||
}}
|
||||
'data': {'var1': {'list_join': ['', ['1', '2']]}}}}
|
||||
tmpl = template.Template(hot_newton_tpl_empty)
|
||||
stack = parser.Stack(utils.dummy_context(), 'test_stack', tmpl)
|
||||
resolved = self.resolve(snippet, tmpl, stack=stack)
|
||||
|
|
Loading…
Reference in New Issue