I have a Mistral workflow (below) that has a line of Jinja with multiple expressions in it. This is 100% valid Jinja that renders properly as show in code below. In Mistral i receive the following error:
2017-08-16 13:27:27.700 935 ERROR mistral.engine.task_handler [-] Failed to handle action completion [error=Can not evaluate Jinja expression [expression= _.directory }}/{{ _.filename , error=chunk after expression, data={}], wf=examples.broken_jinja_example, task=create_path_jinja, action=std.noop]:
Traceback (most recent call last):
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/engine/task_handler.py", line 105, in _on_action_complete
task.on_action_complete(action_ex)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/osprofiler/profiler.py", line 153, in wrapper
return f(*args, **kwargs)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/engine/tasks.py", line 264, in on_action_complete
self.complete(state, state_info)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/osprofiler/profiler.py", line 153, in wrapper
return f(*args, **kwargs)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/engine/tasks.py", line 163, in complete
data_flow.publish_variables(self.task_ex, self.task_spec)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/workflow/data_flow.py", line 211, in publish_variables
task_ex.published = expr.evaluate_recursively(data, expr_ctx)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/__init__.py", line 96, in evaluate_recursively
data[key] = _evaluate_item(data[key], context)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/__init__.py", line 79, in _evaluate_item
return evaluate(item, context)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/__init__.py", line 71, in evaluate
return evaluator.evaluate(expression, context)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/jinja_expression.py", line 140, in evaluate
result = JinjaEvaluator.evaluate(patterns[0][1], data_context)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/jinja_expression.py", line 89, in evaluate
", data=%s]" % (expression, str(e), data_context)
JinjaEvaluationException: Can not evaluate Jinja expression [expression= _.directory }}/{{ _.filename , error=chunk after expression, data={}]
: JinjaEvaluationException: Can not evaluate Jinja expression [expression= _.directory }}/{{ _.filename , error=chunk after expression, data={}]
2017-08-16 13:27:27.700 935 INFO workflow_trace [-] Task 'create_path_jinja' (b7758c32-e182-4dfa-8f5e-4b0437473372) [SUCCESS -> ERROR, msg=Failed to handle action completion [error=Can not evaluate Jinja expression [expression= _.directory }}/{{ _.filename , error=chunk after expression, data={}], wf=examples.broken_jinja_example, task=create_path_jinja, action=std.noop]:
Traceback (most recent call last):
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/engine/task_handler.py", line 105, in _on_action_complete
task.on_action_complete(action_ex)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/osprofiler/profiler.py", line 153, in wrapper
return f(*args, **kwargs)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/engine/tasks.py", line 264, in on_action_complete
self.complete(state, state_info)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/osprofiler/profiler.py", line 153, in wrapper
return f(*args, **kwargs)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/engine/tasks.py", line 163, in complete
data_flow.publish_variables(self.task_ex, self.task_spec)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/workflow/data_flow.py", line 211, in publish_variables
task_ex.published = expr.evaluate_recursively(data, expr_ctx)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/__init__.py", line 96, in evaluate_recursively
data[key] = _evaluate_item(data[key], context)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/__init__.py", line 79, in _evaluate_item
return evaluate(item, context)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/__init__.py", line 71, in evaluate
return evaluator.evaluate(expression, context)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/jinja_expression.py", line 140, in evaluate
result = JinjaEvaluator.evaluate(patterns[0][1], data_context)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/jinja_expression.py", line 89, in evaluate
", data=%s]" % (expression, str(e), data_context)
JinjaEvaluationException: Can not evaluate Jinja expression [expression= _.directory }}/{{ _.filename , error=chunk after expression, data={}]
] (execution_id=bf923a97-430b-4c4d-90ec-b5d67ac3b4a5): JinjaEvaluationException: Can not evaluate Jinja expression [expression= _.directory }}/{{ _.filename , error=chunk after expression, data={}]
2017-08-16 13:27:27.704 935 INFO workflow_trace [-] Workflow 'examples.broken_jinja_example' [RUNNING -> ERROR, msg=Failed to handle action completion [error=Can not evaluate Jinja expression [expression= _.directory }}/{{ _.filename , error=chunk after expression, data={}], wf=examples.broken_jinja_example, task=create_path_jinja, action=std.noop]:
Traceback (most recent call last):
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/engine/task_handler.py", line 105, in _on_action_complete
task.on_action_complete(action_ex)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/osprofiler/profiler.py", line 153, in wrapper
return f(*args, **kwargs)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/engine/tasks.py", line 264, in on_action_complete
self.complete(state, state_info)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/osprofiler/profiler.py", line 153, in wrapper
return f(*args, **kwargs)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/engine/tasks.py", line 163, in complete
data_flow.publish_variables(self.task_ex, self.task_spec)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/workflow/data_flow.py", line 211, in publish_variables
task_ex.published = expr.evaluate_recursively(data, expr_ctx)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/__init__.py", line 96, in evaluate_recursively
data[key] = _evaluate_item(data[key], context)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/__init__.py", line 79, in _evaluate_item
return evaluate(item, context)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/__init__.py", line 71, in evaluate
return evaluator.evaluate(expression, context)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/jinja_expression.py", line 140, in evaluate
result = JinjaEvaluator.evaluate(patterns[0][1], data_context)
File "/opt/stackstorm/mistral/lib/python2.7/site-packages/mistral/expressions/jinja_expression.py", line 89, in evaluate
", data=%s]" % (expression, str(e), data_context)
JinjaEvaluationException: Can not evaluate Jinja expression [expression= _.directory }}/{{ _.filename , error=chunk after expression, data={}]
] (execution_id=bf923a97-430b-4c4d-90ec-b5d67ac3b4a5): JinjaEvaluationException: Can not evaluate Jinja expression [expression= _.directory }}/{{ _.filename , error=chunk after expression, data={}]
---
description: Workflow that reproduces a problem in Mistral with Jinja expressions
enabled: true
runner_type: mistral-v2
entry_point: workflows/broken_jinja_example.yaml
name: broken_jinja_example
pack: examples
parameters:
directory:
default: /opt/stackstorm/configs
type: string
filename:
default: test.yaml
type: string
version: '2.0'
examples.broken_jinja_example:
description: Workflow that reproduces a problem in Mistral with Jinja expressions
type: direct
input:
- directory
- filename
output:
yaql_path: "{{ _.yaql_path }}"
jinja_path: "{{ _.jinja_path }}"
tasks:
create_path_yaql:
action: std.noop
publish:
yaql_path: <% $.directory %>/<% $.filename %>
on-success:
- create_path_jinja
create_path_jinja:
action: std.noop
publish:
jinja_path: "{{ _.directory }}/{{ _.filename }}"
#!/usr/bin/env python
import jinja2
import os
class JinjaUtils:
@staticmethod
def render_str(jinja_template_str, context):
env = jinja2.Environment()
tmpl = env.from_string(jinja_template_str)
return tmpl.render(context)
if __name__ == "__main__":
context = {'_': {'directory': '/opt/stackstorm/configs',
'filename': 'test.yaml'} }
template = "{{ _.directory }}/{{ _.filename }}"
print JinjaUtils.render_str(template, context)
So, i think i figured out what is going on here... but haven't figured out how to fix it yet.
Looking at the mistral jinja expression code here:
https://github.com/StackStorm/mistral/blob/master/mistral/expressions/jinja_expression.py#L123-L126
It's trying to match the regex `({{(.*)}})' to the pattern.
https://github.com/StackStorm/mistral/blob/master/mistral/expressions/jinja_expression.py#L30
Well according to the following regex breakdown:
https://regex101.com/r/05FFax/1

The regex is matching out the outside {{ }} instead of parsing out each group individually. This regex matching, or the logic here needs to change. I'm not sure what it needs to change to yet.
After doing some regex experimentation i think we want to change the regex from
({{(.*)}})
to
({{(.*?)}})
This makes the "match everything" .* non-greedy and stop at the first }} it finds, instead of greedily consuming the rest of the string at stopping at the last }}.

Yup, that seems to fix the issue. Working in v2.4. Care to open a PR @nmaludy with a test : https://github.com/StackStorm/mistral/blob/master/mistral/tests/unit/expressions/test_jinja_expression.py. Thanks! 馃檪
@humblearner already on it https://github.com/StackStorm/mistral/pull/32 :smile:
Submitted to OpenStack Mistral upstream for review https://review.openstack.org/502198
@m4dcoder This got merged into Mistral and is available on GitHub https://github.com/openstack/mistral/commit/2b985feb0b37a6f9fbe506250885a36305bfabaf
What's the process for getting this merged into st2mistral? Should i create a merge PR over in that project? Should i just let you guys handle it?
Fix verified (using w/f in description):
vagrant@u16:/opt/stackstorm/packs/default/actions$ st2 run default.broken_jinja_example
...
id: 5a00d1c5de59a42542829b99
action.ref: default.broken_jinja_example
parameters: None
status: succeeded
start_timestamp: 2017-11-06T21:19:01.136671Z
end_timestamp: 2017-11-06T21:19:06.980924Z
result:
extra:
state: SUCCESS
state_info: null
jinja_path: /opt/stackstorm/configs/test.yaml
tasks:
- created_at: '2017-11-06 21:19:01'
id: 204c5084-daa7-44bd-8187-601cfe69836a
input: null
name: create_path_yaql
published:
yaql_path: /opt/stackstorm/configs/test.yaml
result: null
state: SUCCESS
state_info: null
updated_at: '2017-11-06 21:19:01'
workflow_execution_id: 5aed6d2c-970b-4e69-a80a-ba6f1323fada
workflow_name: default.broken_jinja_example
- created_at: '2017-11-06 21:19:01'
id: 64bc89c1-3b3e-4e1a-8714-4e5e1e8c841b
input: null
name: create_path_jinja
published:
jinja_path: /opt/stackstorm/configs/test.yaml
result: null
state: SUCCESS
state_info: null
updated_at: '2017-11-06 21:19:01'
workflow_execution_id: 5aed6d2c-970b-4e69-a80a-ba6f1323fada
workflow_name: default.broken_jinja_example
yaql_path: /opt/stackstorm/configs/test.yaml
vagrant@u16:/opt/stackstorm/packs/default/actions$ st2 --version
st2 2.5.0
Most helpful comment
@humblearner already on it https://github.com/StackStorm/mistral/pull/32 :smile: