Example #1
0
def create_action_execution(values, session=None):
    a_ex = models.ActionExecution()

    a_ex.update(values.copy())

    try:
        a_ex.save(session=session)
    except db_exc.DBDuplicateEntry as e:
        raise exc.DBDuplicateEntryError(
            "Duplicate entry for ActionExecution: %s" % e.columns
        )

    return a_ex
Example #2
0
    def test_continue_workflow(self):
        self.wf_ex.params = {'task_name': 'task2'}

        # Assume task1 completed.
        task1_ex = self._create_task_execution('task1', states.SUCCESS)
        task1_ex.executions.append(
            models.ActionExecution(
                name='std.echo',
                workflow_name='wf',
                state=states.SUCCESS,
                output={'result': 'Hey'},
                accepted=True
            )
        )

        cmds = self.wf_ctrl.continue_workflow()

        task1_ex.processed = True

        self.assertEqual(1, len(cmds))
        self.assertEqual('task2', cmds[0].task_spec.get_name())

        # Now assume task2 completed.
        task2_ex = self._create_task_execution('task2', states.SUCCESS)
        task2_ex.executions.append(
            models.ActionExecution(
                name='std.echo',
                workflow_name='wf',
                state=states.SUCCESS,
                output={'result': 'Hi!'},
                accepted=True
            )
        )

        cmds = self.wf_ctrl.continue_workflow()

        task1_ex.processed = True

        self.assertEqual(0, len(cmds))
    def test_action_executions(self):
        # Store one task with two invocations.
        with db_api.transaction():
            wf_ex = db_api.create_workflow_execution(WF_EXECS[0])

            values = copy.copy(TASK_EXECS[0])
            values.update({'workflow_execution_id': wf_ex.id})

            task = db_api.create_task_execution(values)

            self.assertEqual(0, len(task.executions))

            a_ex1 = db_models.ActionExecution()
            a_ex2 = db_models.ActionExecution()

            task.executions.append(a_ex1)
            task.executions.append(a_ex2)

            self.assertEqual(2, len(task.executions))

        # Make sure associated objects were saved.
        with db_api.transaction():
            task = db_api.get_task_execution(task.id)

            self.assertEqual(2, len(task.executions))

            self.assertNotIsInstance(task.executions[0].task_execution, list)

        # Remove associated objects from collection.
        with db_api.transaction():
            task = db_api.get_task_execution(task.id)

            del task.executions[:]

        # Make sure associated objects were deleted.
        with db_api.transaction():
            task = db_api.get_task_execution(task.id)

            self.assertEqual(0, len(task.executions))
Example #4
0
    def start_action(self,
                     action_name,
                     action_input,
                     description=None,
                     **params):
        with db_api.transaction():
            action = action_handler.build_action_by_name(action_name)

            action.validate_input(action_input)

            sync = params.get('run_sync')
            save = params.get('save_result')
            target = params.get('target')

            is_action_sync = action.is_sync(action_input)

            if sync and not is_action_sync:
                raise exceptions.InputException(
                    "Action does not support synchronous execution.")

            if not sync and (save or not is_action_sync):
                action.schedule(action_input, target)

                return action.action_ex.get_clone()

            output = action.run(action_input, target, save=False)

            state = states.SUCCESS if output.is_success() else states.ERROR

            if not save:
                # Action execution is not created but we need to return similar
                # object to a client anyway.
                return db_models.ActionExecution(name=action_name,
                                                 description=description,
                                                 input=action_input,
                                                 output=output.to_dict(),
                                                 state=state)

            action_ex_id = u.generate_unicode_uuid()

            values = {
                'id': action_ex_id,
                'name': action_name,
                'description': description,
                'input': action_input,
                'output': output.to_dict(),
                'state': state,
            }

            return db_api.create_action_execution(values)
Example #5
0
    def test_get_task_execution_result(self):
        task_ex = models.TaskExecution(
            name='task1',
            spec={
                "version": '2.0',
                'name': 'task1',
                'with-items': 'var in [1]',
                'type': 'direct',
                'action': 'my_action'
            },
            runtime_context={'with_items_context': {
                'count': 1
            }})

        task_ex.action_executions = [
            models.ActionExecution(name='my_action',
                                   output={'result': 1},
                                   accepted=True,
                                   runtime_context={'index': 0})
        ]

        self.assertEqual([1], data_flow.get_task_execution_result(task_ex))

        task_ex.action_executions.append(
            models.ActionExecution(name='my_action',
                                   output={'result': 1},
                                   accepted=True,
                                   runtime_context={'index': 0}))

        task_ex.action_executions.append(
            models.ActionExecution(name='my_action',
                                   output={'result': 1},
                                   accepted=False,
                                   runtime_context={'index': 0}))

        self.assertEqual([1, 1], data_flow.get_task_execution_result(task_ex))
Example #6
0
    def start_action(self, action_name, action_input,
                     description=None, **params):
        with db_api.transaction():
            action_def = action_handler.resolve_definition(action_name)
            resolved_action_input = action_handler.get_action_input(
                action_name,
                action_input
            )
            action = a_m.get_action_class(action_def.name)(
                **resolved_action_input
            )

            # If we see action is asynchronous, then we enforce 'save_result'.
            if params.get('save_result') or not action.is_sync():
                action_ex = action_handler.create_action_execution(
                    action_def,
                    resolved_action_input,
                    description=description
                )

                action_handler.run_action(
                    action_def,
                    resolved_action_input,
                    action_ex.id,
                    params.get('target')
                )

                return action_ex.get_clone()
            else:
                output = action_handler.run_action(
                    action_def,
                    resolved_action_input,
                    target=params.get('target'),
                    async=False
                )

                return db_models.ActionExecution(
                    name=action_name,
                    description=description,
                    input=action_input,
                    output=output
                )
from mistral.tests.unit.api import base
from mistral.utils import rest_utils
from mistral.workflow import states
from mistral_lib import actions as ml_actions

# This line is needed for correct initialization of messaging config.
oslo_messaging.get_rpc_transport(cfg.CONF)

ACTION_EX_DB = models.ActionExecution(
    id='123',
    workflow_name='flow',
    task_execution=models.TaskExecution(name='task1'),
    task_execution_id='333',
    state=states.SUCCESS,
    state_info=states.SUCCESS,
    tags=['foo', 'fee'],
    name='std.echo',
    description='something',
    accepted=True,
    input={},
    output={},
    created_at=datetime.datetime(1970, 1, 1),
    updated_at=datetime.datetime(1970, 1, 1))

AD_HOC_ACTION_EX_DB = models.ActionExecution(
    id='123',
    state=states.SUCCESS,
    state_info=states.SUCCESS,
    tags=['foo', 'fee'],
    name='std.echo',
    description='something',
Example #8
0
 def get_action_ex(accepted, state, index):
     return models.ActionExecution(accepted=accepted,
                                   state=state,
                                   runtime_context={'index': index})
Example #9
0
    def test_continue_workflow(self, get_task_execution):
        wf_text = """---
        version: '2.0'

        wf:
          type: direct

          tasks:
            task1:
              action: std.echo output="Hey"
              publish:
                res1: <% $.task1 %>
              on-complete:
                - task2: <% $.res1 = 'Hey' %>
                - task3: <% $.res1 = 'Not Hey' %>

            task2:
              action: std.echo output="Hi"

            task3:
              action: std.echo output="Hoy"
        """

        self._prepare_test(wf_text)

        # Workflow execution is in initial step. No running tasks.
        cmds = self.wf_ctrl.continue_workflow()

        self.assertEqual(1, len(cmds))

        cmd = cmds[0]

        self.assertIs(self.wf_ctrl.wf_ex, cmd.wf_ex)
        self.assertIsNotNone(cmd.task_spec)
        self.assertEqual('task1', cmd.task_spec.get_name())
        self.assertEqual(states.RUNNING, self.wf_ex.state)

        # Assume that 'task1' completed successfully.
        task1_ex = self._create_task_execution('task1', states.SUCCESS)
        task1_ex.published = {'res1': 'Hey'}

        get_task_execution.return_value = task1_ex

        task1_ex.executions.append(
            models.ActionExecution(name='std.echo',
                                   workflow_name='wf',
                                   state=states.SUCCESS,
                                   output={'result': 'Hey'},
                                   accepted=True,
                                   runtime_context={'index': 0}))

        cmds = self.wf_ctrl.continue_workflow()

        task1_ex.processed = True

        self.assertEqual(1, len(cmds))
        self.assertEqual('task2', cmds[0].task_spec.get_name())

        self.assertEqual(states.RUNNING, self.wf_ex.state)
        self.assertEqual(states.SUCCESS, task1_ex.state)

        # Now assume that 'task2' completed successfully.
        task2_ex = self._create_task_execution('task2', states.SUCCESS)
        task2_ex.executions.append(
            models.ActionExecution(name='std.echo',
                                   workflow_name='wf',
                                   state=states.SUCCESS,
                                   output={'result': 'Hi'},
                                   accepted=True))

        cmds = self.wf_ctrl.continue_workflow()

        task2_ex.processed = True

        self.assertEqual(0, len(cmds))
Example #10
0
    def start_action(self,
                     action_name,
                     action_input,
                     description=None,
                     namespace='',
                     **params):
        with db_api.transaction():
            engine_action = action_handler.build_action_by_name(
                action_name, namespace=namespace)

            action_desc = engine_action.action_desc

            action_desc.check_parameters(action_input)

            sync = params.get('run_sync')
            save = params.get('save_result')
            target = params.get('target')
            timeout = params.get('timeout')

            # In order to know if it's sync or not we have to instantiate
            # the actual runnable action.
            action = action_desc.instantiate(action_input, {})

            is_action_sync = action.is_sync()

            if sync and not is_action_sync:
                raise exceptions.InputException(
                    "Action does not support synchronous execution.")

            if not sync and (save or not is_action_sync):
                engine_action.schedule(action_input, target, timeout=timeout)

                return engine_action.action_ex.get_clone()

            output = engine_action.run(action_input,
                                       target,
                                       save=False,
                                       timeout=timeout)

            state = states.SUCCESS if output.is_success() else states.ERROR

            if not save:
                # Action execution is not created but we need to return similar
                # object to the client anyway.
                return db_models.ActionExecution(name=action_name,
                                                 description=description,
                                                 input=action_input,
                                                 output=output.to_dict(),
                                                 state=state,
                                                 workflow_namespace=namespace)

            action_ex_id = u.generate_unicode_uuid()

            values = {
                'id': action_ex_id,
                'name': action_name,
                'description': description,
                'input': action_input,
                'output': output.to_dict(),
                'state': state,
                'is_sync': is_action_sync,
                'workflow_namespace': namespace
            }

            return db_api.create_action_execution(values)
Example #11
0
from mistral.db.v2 import api as db_api
from mistral.db.v2.sqlalchemy import models
from mistral.engine import rpc
from mistral import exceptions as exc
from mistral.tests.unit.api import base
from mistral.workflow import states
from mistral.workflow import utils as wf_utils

action_ex = models.ActionExecution(
    id='123',
    workflow_name='flow',
    task_execution=models.TaskExecution(name='task1'),
    task_execution_id='333',
    state=states.SUCCESS,
    state_info=states.SUCCESS,
    tags=['foo', 'fee'],
    name='std.echo',
    description='something',
    accepted=True,
    input={},
    output={},
    created_at=datetime.datetime(1970, 1, 1),
    updated_at=datetime.datetime(1970, 1, 1))

ACTION_EXEC = {
    'id': '123',
    'workflow_name': 'flow',
    'task_execution_id': '333',
    'task_name': 'task1',
    'state': 'SUCCESS',
    'state_info': 'SUCCESS',