StackStorm / st2

StackStorm (aka "IFTTT for Ops") is event-driven automation for auto-remediation, incident responses, troubleshooting, deployments, and more for DevOps and SREs. Includes rules engine, workflow, 160 integration packs with 6000+ actions (see https://exchange.stackstorm.org) and ChatOps. Installer at https://docs.stackstorm.com/install/index.html
https://stackstorm.com/
Apache License 2.0
6.07k stars 749 forks source link

Published mistral variables are not available in context immediately #3554

Closed nmaludy closed 5 years ago

nmaludy commented 7 years ago

I have a mistral workflow that returns a fairly complex data structure. In order to decompose the parsing steps i tried parsing incrementally and assigning to different publish: variables: Unfortunately it seems that the published variables are not made available immediately to the context.

Version with error:

version: '2.0'

menandmice.wf_add_dns_zone:
  description: >
    A sample workflow that demonstrates how to create a master DNS zone
    and several slave zones on slave servers.
    type: direct
  input:
    - session
    - server
    - zone_name
    - master_server
    - slave_servers
  output:
    master_server_ref: "{{ _.master_server_ref }}"
    master_server_ip: "{{ _.master_server_ip }}"
  tasks:
    get_master_server:
      action: menandmice.get_dns_servers
      input:
        session: "{{ _.session }}"
        server: "{{ _.server }}"
        filter: "name: {{ _.master_server }}"
      publish:
        master_server_arr: "{{ task('get_master_server').result.result.dnsServers.dnsServer }}"
        master_server_obj: "{{ _master_server_arr[0] }}"
        master_server_ref: "{{ _.master_server_obj.ref }}"
        master_server_ip: "{{ _.master_server_obj.address }}"

Error

2017-07-06 23:52:29.543 7715 ERROR mistral.engine.task_handler [-] Failed to handle action completion [error=Can not evaluate Jinja expression [expression= _.master_server_arr[0] , error='mistral.workflow.data_flow.ContextView object' has no attribute 'master_server_arr', data={}], wf=menandmice.wf_add_dns_zone, task=get_master, action=st2.action]:
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= _.master_server_arr[0] , error='mistral.workflow.data_flow.ContextView object' has no attribute 'master_server_arr', data={}]
: JinjaEvaluationException: Can not evaluate Jinja expression [expression= _.master_server_arr[0] , error='mistral.workflow.data_flow.ContextView object' has no attribute 'master_server_arr', data={}]
2017-07-06 23:52:29.543 7715 INFO workflow_trace [-] Task 'get_master' (93dd4be6-1fde-4dd9-a6eb-9b488efd5a76) [SUCCESS -> ERROR, msg=Failed to handle action completion [error=Can not evaluate Jinja expression [expression= _.master_server_arr[0] , error='mistral.workflow.data_flow.ContextView object' has no attribute 'master_server_arr', data={}], wf=menandmice.wf_add_dns_zone, task=get_master, action=st2.action]:
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= _.master_server_arr[0] , error='mistral.workflow.data_flow.ContextView object' has no attribute 'master_server_arr', data={}]
] (execution_id=5c76e06d-3283-4352-8e55-7ad434b976ab): JinjaEvaluationException: Can not evaluate Jinja expression [expression= _.master_server_arr[0] , error='mistral.workflow.data_flow.ContextView object' has no attribute 'master_server_arr', data={}]
2017-07-06 23:52:29.547 7715 INFO workflow_trace [-] Workflow 'menandmice.wf_add_dns_zone' [RUNNING -> ERROR, msg=Failed to handle action completion [error=Can not evaluate Jinja expression [expression= _.master_server_arr[0] , error='mistral.workflow.data_flow.ContextView object' has no attribute 'master_server_arr', data={}], wf=menandmice.wf_add_dns_zone, task=get_master, action=st2.action]:
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= _.master_server_arr[0] , error='mistral.workflow.data_flow.ContextView object' has no attribute 'master_server_arr', data={}]
] (execution_id=5c76e06d-3283-4352-8e55-7ad434b976ab): JinjaEvaluationException: Can not evaluate Jinja expression [expression= _.master_server_arr[0] , error='mistral.workflow.data_flow.ContextView object' has no attribute 'master_server_arr', data={}]

Version that works:

version: '2.0'

menandmice.wf_add_dns_zone:
  description: >
    A sample workflow that demonstrates how to create a master DNS zone
    and several slave zones on slave servers.
    type: direct
  input:
    - session
    - server
    - zone_name
    - master_server
    - slave_servers
  output:
    master_server_ref: "{{ _.master_server_ref }}"
    master_server_ip: "{{ _.master_server_ip }}"
  tasks:
    get_master_server:
      action: menandmice.get_dns_servers
      input:
        session: "{{ _.session }}"
        server: "{{ _.server }}"
        filter: "name: {{ _.master_server }}"
      publish:
        master_server_obj: "{{ task('get_master_server').result.result.dnsServers.dnsServer[0] }}"\
      on-success:
        - parse_master__server

    parse_master_server:
      action: std.noop
      publish:
        master_server_ref: "{{ _.master_server_obj.ref }}"
        master_server_ip: "{{ _.master_server_obj.address }}"

I'll see if i can get a more simple example sometime tomorrow and also will test with YAQL.

Not sure if this is a mistral problem, a stackstorm problem, or expected behavior?

arm4b commented 7 years ago

For me it sounds like a typical/expected issue, when variable is not yet published/created and you're trying to use it too early:

      publish:
        master_server_arr: "{{ task('get_master_server').result.result.dnsServers.dnsServer }}"
        master_server_obj: "{{ _master_server_arr[0] }}"

But I'll leave it for @m4dcoder to clarify & answer if there is a room for improvement in Mistral itself.

nmaludy commented 7 years ago

@armab @m4dcoder it doesn't seem to be jinja specific, the following YAQL does not work either:

version: '2.0'

menandmice.wf_test:
  description: >
    A sample workflow that demonstrates how to create a master DNS zone
    and several slave zones on slave servers.
    type: direct
  input:
    - session
    - server
    - zone_name
    - master_server
    - slave_servers
  output:
    master_server_ref: <% $.master_server_ref %>
    master_server_ip: <% $.master_server_ip %>
  tasks:
    get_master_server:
      action: menandmice.get_dns_servers
      input:
        session: <% $.session %>
        server: <% $.server %>
        filter: "name: <% $.master_server %>"
      publish:
        master_server_arr: <% task(get_master_server).result.result.dnsServers.dnsServer %>
        master_server_obj: <% $.master_server_arr[0] %>
        master_server_ref: <% $.master_server_obj.ref %>
        master_server_ip: <% $.master_server_obj.address %>

I'm guessing/leaning towards this being a mistral issue not updating the context when each variable is published but only when the task is completed.

I tested this out by trying to print the published variables within the publish stanza.

version: '2.0'

menandmice.wf_test:
  description: >
    A sample workflow that demonstrates how to create a master DNS zone
    and several slave zones on slave servers.
    type: direct
  input:
    - session
    - server
    - zone_name
    - master_server
    - slave_servers
  output:
    master_server_arr: <% $.master_server_arr %>
    master_published: <% $.master_published %>
  tasks:
    get_master_server:
      action: menandmice.get_dns_servers
      input:
        session: <% $.session %>
        server: <% $.server %>
        filter: "name: <% $.master_server %>"
      publish:
        master_server_arr: <% task(get_master_server).result.result.dnsServers.dnsServer %>
        master_published: <% task(get_master_server).published %>

It looks like that is empty at the time of execution:

| status          | succeeded (7s elapsed)                                       |
| start_timestamp | Fri, 07 Jul 2017 13:34:15 UTC                                |
| end_timestamp   | Fri, 07 Jul 2017 13:34:22 UTC                                |
| result          | {                                                            |
|                 |     "master_published": {},  
nmaludy commented 7 years ago

Did a little digging on my own. If i'm looking at the code right the publish starts here:

https://github.com/StackStorm/mistral/blob/master/mistral/engine/tasks.py#L163

Which then runs the publish function here:

https://github.com/StackStorm/mistral/blob/master/mistral/workflow/data_flow.py#L187-L211

Then each publish expression is then evaluated here:

https://github.com/StackStorm/mistral/blob/master/mistral/expressions/__init__.py#L88-L103

In the expression evaluation it appears that the context is not updated at all during those calls, instead the data is written to a new dict that this returned from the evaluation. This new dict is then written to the task executions 'published` variable (which i assume is then merged into the workflows context at some point.. didn't get that far).

Since this is a mistral issue are there any thoughts? Do you think this is a worthwhile feature to request? Should i go a head and close this case?

nmaludy commented 7 years ago

Digging through mistral bug reports, looks like it's a known bug/feature request: https://bugs.launchpad.net/mistral/+bug/1680109

stale[bot] commented 5 years ago

Thanks for contributing to this issue. As it has been 90 days since the last activity, we are automatically marking is as stale. If this issue is not relevant or applicable anymore (problem has been fixed in a new version or similar), please close the issue or let us know so we can close it. On the contrary, if the issue is still relevant, there is nothing you need to do, but if you have any additional details or context which would help us when working on this issue, please include it as a comment to this issue.

nmaludy commented 5 years ago

Closing in favor of Orquesta.