deb-mistral/mistral/workflow/data_flow.py
Nikolay Mahotkin 17d180956c Fix dataflow work
* Unit test

Closes-bug: #1376682

Change-Id: I6fdd6f9cc705bf016646d5bd5fcf98bec450cadb
2014-10-06 11:27:24 +04:00

157 lines
4.4 KiB
Python

# -*- 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 copy
from oslo.config import cfg
from mistral import expressions as expr
from mistral.openstack.common import log as logging
from mistral.services import trusts
from mistral import utils
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
def prepare_db_task(task_db, task_spec, upstream_task_specs, exec_db,
cause_task_db=None):
"""Prepare Data Flow properties ('in_context' and 'input')
of given DB task.
:param task_db: DB task to prepare.
:param task_spec: Task specification.
:param upstream_task_specs: Specifications of workflow upstream tasks.
:param exec_db: Execution DB model.
"""
upstream_db_tasks = [
filter(lambda t: t.name == t_spec.get_name(), exec_db.tasks)[0]
for t_spec in upstream_task_specs
]
task_db.in_context = utils.merge_dicts(
copy.copy(exec_db.context),
_evaluate_upstream_context(upstream_db_tasks)
)
if cause_task_db:
# TODO(nmakhotkin): Do it using _evaluate_upstream_context()
# TODO(rakhmerov): Think if Data Flow should be a part of wf handler.
task_db.in_context = utils.merge_dicts(
task_db.in_context,
evaluate_outbound_context(cause_task_db)
)
task_db.input = evaluate_task_input(
task_spec,
task_db.in_context
)
def evaluate_task_input(task_spec, context):
return expr.evaluate_recursively(task_spec.get_input(), context)
def _evaluate_upstream_context(upstream_db_tasks):
ctx = {}
for t_db in upstream_db_tasks:
utils.merge_dicts(ctx, evaluate_outbound_context(t_db))
return ctx
def evaluate_task_output(task_spec, raw_result):
"""Evaluates task output given a raw task result from action/workflow.
:param task_spec: Task specification
:param raw_result: Raw task result that comes from action/workflow
(before publisher). Instance of mistral.workflow.base.TaskResult
:return: Complete task output that goes to Data Flow context.
"""
publish_dict = task_spec.get_publish()
# Evaluate 'publish' clause using raw result as a context.
output = expr.evaluate_recursively(publish_dict, raw_result.data) or {}
# Add raw task result to task output under key 'task'
output['task'] = {task_spec.get_name(): raw_result.data}
return output
def evaluate_workflow_output(wf_spec, context):
"""Evaluates workflow output.
:param wf_spec: Workflow specification.
:param context: Final Data Flow context (cause task's outbound context).
"""
output_dict = wf_spec.get_output()
# Evaluate 'publish' clause using raw result as a context.
output = expr.evaluate_recursively(output_dict, context)
return output or context
def evaluate_outbound_context(task_db):
"""Evaluates task outbound Data Flow context.
This method assumes that complete task output (after publisher etc.)
has already been evaluated.
:param task_db: DB task.
:return: Outbound task Data Flow context.
"""
in_context = copy.deepcopy(dict(task_db.in_context)) \
if task_db.in_context is not None else {}
return utils.merge_dicts(
in_context,
task_db.output
)
def add_openstack_data_to_context(workflow_db, context):
if context is None:
context = {}
if CONF.pecan.auth_enable:
workbook_ctx = trusts.create_context(
workflow_db.trust_id,
workflow_db.project_id
)
if workbook_ctx:
context.update({'openstack': workbook_ctx.to_dict()})
return context
def add_execution_to_context(exec_db, context):
if context is None:
context = {}
context['__execution'] = {
'id': exec_db.id,
'wf_spec': exec_db['wf_spec'],
'start_params': exec_db.start_params,
'input': exec_db.input
}
return context