Beispiel #1
0
def get_model_from_ref(db_api, reference):
    if reference is None:
        raise db.StackStormDBObjectNotFoundError('No reference supplied.')
    model_id = reference.get('id', None)
    if model_id is not None:
        return db_api.get_by_id(model_id)
    model_name = reference.get('name', None)
    if model_name is None:
        raise db.StackStormDBObjectNotFoundError('Both name and id are None.')
    return db_api.get_by_name(model_name)
Beispiel #2
0
    def get(self, *args, **kwargs):
        exclude_fields = kwargs.pop('exclude_fields', None)
        raise_exception = kwargs.pop('raise_exception', False)
        only_fields = kwargs.pop('only_fields', None)

        args = self._process_arg_filters(args)

        instances = self.model.objects(*args, **kwargs)

        if exclude_fields:
            instances = instances.exclude(*exclude_fields)

        if only_fields:
            try:
                instances = instances.only(*only_fields)
            except (mongoengine.errors.LookUpError, AttributeError) as e:
                msg = (
                    'Invalid or unsupported include attribute specified: %s' %
                    six.text_type(e))
                raise ValueError(msg)

        instance = instances[0] if instances else None
        log_query_and_profile_data_for_queryset(queryset=instances)

        if not instance and raise_exception:
            msg = 'Unable to find the %s instance. %s' % (self.model.__name__,
                                                          kwargs)
            raise db_exc.StackStormDBObjectNotFoundError(msg)

        return instance
Beispiel #3
0
    def _get_one_by_id(
        self,
        id,
        requester_user,
        permission_type,
        exclude_fields=None,
        from_model_kwargs=None,
    ):
        """Override ResourceController._get_one_by_id to contain scope of Inquiries UID hack
        :param exclude_fields: A list of object fields to exclude.
        :type exclude_fields: ``list``
        """
        LOG.debug('Retrieving action execution for inquiry "%s".' % id)

        execution_db = self._get_by_id(resource_id=id,
                                       exclude_fields=exclude_fields)

        if not execution_db:
            raise db_exceptions.StackStormDBObjectNotFoundError()

        # Inquiry currently does not have it's own database model and share with ActionExecution.
        # The object uid is in the format of "execution:<id>". To allow RBAC to resolve correctly
        # for inquiries, we're overriding the "get_uid" function so the object uid can be set to
        # "inquiry:<id>".
        #
        # TODO (mierdin): All of this should be removed once Inquiries get their own DB model.
        if (execution_db and getattr(execution_db, "runner", None) and
                execution_db.runner.get("runner_module") == INQUIRY_RUNNER):
            execution_db.get_uid = get_uid

        LOG.debug('Checking permission on inquiry "%s".' % id)

        if permission_type:
            rbac_utils = get_rbac_backend().get_utils_class()
            rbac_utils.assert_user_has_resource_db_permission(
                user_db=requester_user,
                resource_db=execution_db,
                permission_type=permission_type,
            )

        from_model_kwargs = from_model_kwargs or {}
        from_model_kwargs.update(self.from_model_kwargs)
        result = self.model.from_model(execution_db, **from_model_kwargs)

        return result
Beispiel #4
0
class MistralQuerierTest(DbTestCase):
    @classmethod
    def setUpClass(cls):
        super(MistralQuerierTest, cls).setUpClass()

        # Override the retry configuration here otherwise st2tests.config.parse_args
        # in DbTestCase.setUpClass will reset these overrides.
        cfg.CONF.set_override('retry_exp_msec', 100, group='mistral')
        cfg.CONF.set_override('retry_exp_max_msec', 200, group='mistral')
        cfg.CONF.set_override('retry_stop_max_msec', 200, group='mistral')

        # Register query module.
        cls.query_module = get_query_module('mistral-v2')

    def setUp(self):
        super(MistralQuerierTest, self).setUp()
        self.querier = self.query_module.get_instance()

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_running_exec_running_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'RUNNING', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_running_exec_running_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'RUNNING', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_running_exec_succeeded_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'SUCCESS', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_running_exec_succeeded_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'SUCCESS', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_running_exec_succeeded_tasks_completed_child_running(
            self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'SUCCESS', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_running_exec_failed_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'ERROR', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_FAILED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_running_exec_failed_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'ERROR', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_canceling_exec_canceled_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'CANCELLED', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_canceling_exec_canceled_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'CANCELLED', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_canceling_exec_canceled_tasks_waiting(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'CANCELLED', MOCK_WF_TASKS_WAITING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_PAUSED,
                           MOCK_CHILD_ACTIONEXECUTION_PAUSED
                       ]))
    def test_determine_status_wf_canceling_exec_canceled_tasks_paused(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'CANCELLED', MOCK_WF_TASKS_PAUSED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_canceling_exec_running_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'RUNNING', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_canceling_exec_running_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'RUNNING', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_CANCELING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_canceling_exec_running_tasks_waiting(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_CANCELING, 'RUNNING', MOCK_WF_TASKS_WAITING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_running_exec_cancelled_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'CANCELLED', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_PAUSING_CHILD_PAUSED,
                           MOCK_CHILD_ACTIONEXECUTION_PAUSED
                       ]))
    def test_determine_status_wf_pausing_exec_paused_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_PAUSING, 'PAUSED', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_PAUSING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_pausing_exec_paused_tasks_completed_child_running(
            self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_PAUSING, 'PAUSED', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_PAUSING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_pausing_exec_paused_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_PAUSING, 'PAUSED', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_PAUSING_CHILD_PAUSED,
                           MOCK_CHILD_ACTIONEXECUTION_PAUSED
                       ]))
    def test_determine_status_wf_pausing_exec_paused_tasks_paused(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_PAUSING, 'PAUSED', MOCK_WF_TASKS_PAUSED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_PAUSING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_pausing_exec_running_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_PAUSING, 'RUNNING', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_running_exec_paused_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'PAUSED', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSED, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_running_exec_paused_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RUNNING, 'PAUSED', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RESUMING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_resuming_exec_paused_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RESUMING, 'PAUSED', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RESUMING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RESUMING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_determine_status_wf_resuming_exec_running_tasks_completed(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RESUMING, 'RUNNING', MOCK_WF_TASKS_SUCCEEDED)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RESUMING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_resuming_exec_running_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RESUMING, 'RUNNING', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RESUMING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_resuming_exec_paused_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RESUMING, 'PAUSED', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_PAUSING, status)

    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RESUMING_CHILD_RUNNING,
                           MOCK_CHILD_ACTIONEXECUTION_RUNNING
                       ]))
    def test_determine_status_wf_resuming_exec_canceled_tasks_running(self):
        status = self.querier._determine_execution_status(
            MOCK_LIVEACTION_RESUMING, 'CANCELLED', MOCK_WF_TASKS_RUNNING)

        self.assertEqual(action_constants.LIVEACTION_STATUS_CANCELING, status)

    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    def test_get_workflow_result(self):
        result = self.querier._get_workflow_result(uuid.uuid4().hex,
                                                   uuid.uuid4().hex)

        expected = {
            'k1': 'v1',
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        self.assertDictEqual(expected, result)

    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    def test_get_workflow_tasks(self):
        tasks = self.querier._get_workflow_tasks(uuid.uuid4().hex,
                                                 uuid.uuid4().hex)

        expected = copy.deepcopy(MOCK_WF_EX_TASKS_DATA)
        for task in expected:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        for i in range(0, len(tasks)):
            self.assertDictEqual(expected[i], tasks[i])

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

    @mock.patch.object(
        action_utils, 'get_liveaction_by_id',
        mock.MagicMock(
            return_value=MOCK_LIVEACTION_RUNNING_WITH_STREAMING_RESULT))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=[MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(tasks.TaskManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS[1]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query_with_last_query_time(self):
        last_query_time = time.time() - 3

        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT,
                                              last_query_time=last_query_time)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

    @mock.patch.object(
        action_utils, 'get_liveaction_by_id',
        mock.MagicMock(side_effect=db_exc.StackStormDBObjectNotFoundError()))
    def test_query_liveaction_not_found(self):
        self.assertRaises(db_exc.StackStormDBObjectNotFoundError,
                          self.querier.query,
                          uuid.uuid4().hex, MOCK_QRY_CONTEXT)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(
        executions.ExecutionManager, 'get',
        mock.MagicMock(
            side_effect=[requests.exceptions.ConnectionError(), MOCK_WF_EX]))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query_get_workflow_retry(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

        calls = [
            call(MOCK_QRY_CONTEXT['mistral']['execution_id'])
            for i in range(0, 2)
        ]
        executions.ExecutionManager.get.assert_has_calls(calls)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(
        executions.ExecutionManager, 'get',
        mock.MagicMock(side_effect=[requests.exceptions.ConnectionError()] * 4)
    )
    def test_query_get_workflow_retry_exhausted(self):
        self.assertRaises(requests.exceptions.ConnectionError,
                          self.querier.query,
                          uuid.uuid4().hex, MOCK_QRY_CONTEXT)

        calls = [
            call(MOCK_QRY_CONTEXT['mistral']['execution_id'])
            for i in range(0, 2)
        ]
        executions.ExecutionManager.get.assert_has_calls(calls)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(
        executions.ExecutionManager, 'get',
        mock.MagicMock(side_effect=mistralclient_base.APIException(
            error_code=404, error_message='Workflow not found.')))
    def test_query_get_workflow_not_found(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        self.assertEqual(action_constants.LIVEACTION_STATUS_FAILED, status)
        self.assertEqual('Workflow not found.', result)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(
        tasks.TaskManager, 'list',
        mock.MagicMock(side_effect=[
            requests.exceptions.ConnectionError(), MOCK_WF_EX_TASKS
        ]))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query_list_workflow_tasks_retry(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

        mock_call = call(
            workflow_execution_id=MOCK_QRY_CONTEXT['mistral']['execution_id'])
        calls = [mock_call for i in range(0, 2)]
        tasks.TaskManager.list.assert_has_calls(calls)

        calls = [call(MOCK_WF_EX_TASKS[0].id), call(MOCK_WF_EX_TASKS[1].id)]
        tasks.TaskManager.get.assert_has_calls(calls)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(tasks.TaskManager, 'get',
                       mock.MagicMock(side_effect=[
                           requests.exceptions.ConnectionError(),
                           MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]
                       ]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query_get_workflow_tasks_retry(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)

        calls = [
            call(MOCK_WF_EX_TASKS[0].id),
            call(MOCK_WF_EX_TASKS[0].id),
            call(MOCK_WF_EX_TASKS[1].id)
        ]

        tasks.TaskManager.get.assert_has_calls(calls)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(
        tasks.TaskManager, 'list',
        mock.MagicMock(side_effect=[requests.exceptions.ConnectionError()] * 4)
    )
    def test_query_list_workflow_tasks_retry_exhausted(self):
        self.assertRaises(requests.exceptions.ConnectionError,
                          self.querier.query,
                          uuid.uuid4().hex, MOCK_QRY_CONTEXT)

        mock_call = call(
            workflow_execution_id=MOCK_QRY_CONTEXT['mistral']['execution_id'])
        calls = [mock_call for i in range(0, 2)]
        tasks.TaskManager.list.assert_has_calls(calls)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[requests.exceptions.ConnectionError()] * 4)
    )
    def test_query_get_workflow_tasks_retry_exhausted(self):
        self.assertRaises(requests.exceptions.ConnectionError,
                          self.querier.query,
                          uuid.uuid4().hex, MOCK_QRY_CONTEXT)

        calls = [call(MOCK_WF_EX_TASKS[0].id), call(MOCK_WF_EX_TASKS[0].id)]

        tasks.TaskManager.get.assert_has_calls(calls)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=mistralclient_base.APIException(
            error_code=404, error_message='Task not found.')))
    def test_query_get_workflow_tasks_not_found(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        self.assertEqual(action_constants.LIVEACTION_STATUS_FAILED, status)
        self.assertEqual('Task not found.', result)

    def test_query_missing_context(self):
        self.assertRaises(Exception, self.querier.query, uuid.uuid4().hex, {})

    def test_query_missing_mistral_execution_id(self):
        self.assertRaises(Exception, self.querier.query,
                          uuid.uuid4().hex, {'mistral': {}})

    @mock.patch.object(
        action_utils, 'get_liveaction_by_id',
        mock.MagicMock(
            return_value=
            MOCK_LIVEACTION_RUNNING_WITH_OUTDATED_INCOMPLETE_TASKS_STREAMING_RESULT
        ))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_INCOMPLETE_TASKS)
                       )
    @mock.patch.object(tasks.TaskManager, 'get',
                       mock.MagicMock(side_effect=MOCK_WF_EX_INCOMPLETE_TASKS))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query_with_outdated_tasks_in_liveaction_result(self):
        last_query_time = time.time() + 3

        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT,
                                              last_query_time=last_query_time)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_INCOMPLETE_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)
        self.assertDictEqual(expected, result)

    @mock.patch.object(
        action_utils, 'get_liveaction_by_id',
        mock.MagicMock(
            return_value=
            MOCK_LIVEACTION_RUNNING_WITH_UP_TO_DATE_INCOMPLETE_TASKS_STREAMING_RESULT
        ))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_INCOMPLETE_TASKS)
                       )
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(return_value=MOCK_WF_EX_INCOMPLETE_TASKS[1]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_SUCCEEDED,
                           MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED
                       ]))
    def test_query_with_up_to_date_tasks_in_liveaction_result(self):
        last_query_time = time.time() + 3

        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT,
                                              last_query_time=last_query_time)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_INCOMPLETE_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_RUNNING, status)
        self.assertDictEqual(expected, result)

    @mock.patch.object(action_utils, 'get_liveaction_by_id',
                       mock.MagicMock(return_value=MOCK_LIVEACTION_RUNNING))
    @mock.patch.object(executions.ExecutionManager, 'get',
                       mock.MagicMock(return_value=MOCK_WF_EX))
    @mock.patch.object(tasks.TaskManager, 'list',
                       mock.MagicMock(return_value=MOCK_WF_EX_TASKS))
    @mock.patch.object(
        tasks.TaskManager, 'get',
        mock.MagicMock(side_effect=[MOCK_WF_EX_TASKS[0], MOCK_WF_EX_TASKS[1]]))
    @mock.patch.object(ActionExecution, 'get',
                       mock.MagicMock(side_effect=[
                           MOCK_ACTIONEXECUTION_RUNNING_CHILD_REQUESTED,
                           MOCK_CHILD_ACTIONEXECUTION_REQUESTED
                       ]))
    def test_orphaned_execution_child_in_requested_state(self):
        (status, result) = self.querier.query(uuid.uuid4().hex,
                                              MOCK_QRY_CONTEXT)

        expected = {
            'k1': 'v1',
            'tasks': copy.deepcopy(MOCK_WF_EX_TASKS_DATA),
            'extra': {
                'state': MOCK_WF_EX.state,
                'state_info': MOCK_WF_EX.state_info
            }
        }

        for task in expected['tasks']:
            task['input'] = json.loads(task['input'])
            task['result'] = json.loads(task['result'])
            task['published'] = json.loads(task['published'])

        self.assertEqual(action_constants.LIVEACTION_STATUS_SUCCEEDED, status)
        self.assertDictEqual(expected, result)