def test_add_or_update_given_trace_db(self): action_execution_id = 'action_execution_1' rule_id = 'rule_1' trigger_instance_id = 'trigger_instance_1' trace_service.add_or_update_given_trace_db( self.trace_empty, action_executions=[action_execution_id], rules=[rule_id], trigger_instances=[trigger_instance_id]) retrieved_trace_db = Trace.get_by_id(self.trace_empty.id) self.assertEqual(len(retrieved_trace_db.action_executions), 1, 'Expected updated action_executions.') self.assertEqual(retrieved_trace_db.action_executions[0].object_id, action_execution_id, 'Expected updated action_executions.') self.assertEqual(len(retrieved_trace_db.rules), 1, 'Expected updated rules.') self.assertEqual(retrieved_trace_db.rules[0].object_id, rule_id, 'Expected updated rules.') self.assertEqual(len(retrieved_trace_db.trigger_instances), 1, 'Expected updated trigger_instances.') self.assertEqual(retrieved_trace_db.trigger_instances[0].object_id, trigger_instance_id, 'Expected updated trigger_instances.') Trace.delete(retrieved_trace_db) Trace.add_or_update(self.trace_empty)
def test_add_or_update_given_trace_db(self): action_execution_id = 'action_execution_1' rule_id = 'rule_1' trigger_instance_id = 'trigger_instance_1' to_save = copy.copy(self.trace_empty) to_save.id = None saved = trace_service.add_or_update_given_trace_db( to_save, action_executions=[action_execution_id], rules=[rule_id], trigger_instances=[trigger_instance_id]) retrieved_trace_db = Trace.get_by_id(saved.id) self.assertEqual(len(retrieved_trace_db.action_executions), 1, 'Expected updated action_executions.') self.assertEqual(retrieved_trace_db.action_executions[0].object_id, action_execution_id, 'Expected updated action_executions.') self.assertEqual(len(retrieved_trace_db.rules), 1, 'Expected updated rules.') self.assertEqual(retrieved_trace_db.rules[0].object_id, rule_id, 'Expected updated rules.') self.assertEqual(len(retrieved_trace_db.trigger_instances), 1, 'Expected updated trigger_instances.') self.assertEqual(retrieved_trace_db.trigger_instances[0].object_id, trigger_instance_id, 'Expected updated trigger_instances.') # Now add more TraceComponents and validated that they are added properly. saved = trace_service.add_or_update_given_trace_db( retrieved_trace_db, action_executions=[str(bson.ObjectId()), str(bson.ObjectId())], rules=[str(bson.ObjectId())], trigger_instances=[ str(bson.ObjectId()), str(bson.ObjectId()), str(bson.ObjectId()) ]) retrieved_trace_db = Trace.get_by_id(saved.id) self.assertEqual(len(retrieved_trace_db.action_executions), 3, 'Expected updated action_executions.') self.assertEqual(len(retrieved_trace_db.rules), 2, 'Expected updated rules.') self.assertEqual(len(retrieved_trace_db.trigger_instances), 4, 'Expected updated trigger_instances.') Trace.delete(retrieved_trace_db)
def _update_trace(self): """ :rtype: ``dict`` trace_context as a dict; could be None """ trace_db = None try: trace_db = trace_service.get_trace_db_by_trigger_instance( self.trigger_instance ) except: LOG.exception( "No Trace found for TriggerInstance %s.", self.trigger_instance.id ) return None # This would signify some sort of coding error so raise ValueError. if not trace_db: raise ValueError("Trace database not found.") trace_db = trace_service.add_or_update_given_trace_db( trace_db=trace_db, rules=[ trace_service.get_trace_component_for_rule( self.rule, self.trigger_instance ) ], ) return vars(TraceContext(id_=str(trace_db.id), trace_tag=trace_db.trace_tag))
def test_add_or_update_given_trace_db(self): action_execution_id = 'action_execution_1' rule_id = 'rule_1' trigger_instance_id = 'trigger_instance_1' to_save = copy.copy(self.trace_empty) to_save.id = None saved = trace_service.add_or_update_given_trace_db( to_save, action_executions=[action_execution_id], rules=[rule_id], trigger_instances=[trigger_instance_id]) retrieved_trace_db = Trace.get_by_id(saved.id) self.assertEqual(len(retrieved_trace_db.action_executions), 1, 'Expected updated action_executions.') self.assertEqual(retrieved_trace_db.action_executions[0].object_id, action_execution_id, 'Expected updated action_executions.') self.assertEqual(len(retrieved_trace_db.rules), 1, 'Expected updated rules.') self.assertEqual(retrieved_trace_db.rules[0].object_id, rule_id, 'Expected updated rules.') self.assertEqual(len(retrieved_trace_db.trigger_instances), 1, 'Expected updated trigger_instances.') self.assertEqual(retrieved_trace_db.trigger_instances[0].object_id, trigger_instance_id, 'Expected updated trigger_instances.') # Now add more TraceComponents and validated that they are added properly. saved = trace_service.add_or_update_given_trace_db( retrieved_trace_db, action_executions=[str(bson.ObjectId()), str(bson.ObjectId())], rules=[str(bson.ObjectId())], trigger_instances=[str(bson.ObjectId()), str(bson.ObjectId()), str(bson.ObjectId())]) retrieved_trace_db = Trace.get_by_id(saved.id) self.assertEqual(len(retrieved_trace_db.action_executions), 3, 'Expected updated action_executions.') self.assertEqual(len(retrieved_trace_db.rules), 2, 'Expected updated rules.') self.assertEqual(len(retrieved_trace_db.trigger_instances), 4, 'Expected updated trigger_instances.') Trace.delete(retrieved_trace_db)
def _update_trace(self): """ :rtype: ``dict`` trace_context as a dict; could be None """ trace_db = None try: trace_db = trace_service.get_trace_db_by_trigger_instance(self.trigger_instance) except: LOG.exception('No Trace found for TriggerInstance %s.', self.trigger_instance.id) return None # This would signify some sort of coding error so assert. assert trace_db trace_db = trace_service.add_or_update_given_trace_db( trace_db=trace_db, rules=[ trace_service.get_trace_component_for_rule(self.rule, self.trigger_instance) ]) return vars(TraceContext(id_=str(trace_db.id), trace_tag=trace_db.trace_tag))
def _update_trace(self): """ :rtype: ``dict`` trace_context as a dict; could be None """ trace_db = None try: trace_db = trace_service.get_trace_db_by_trigger_instance( self.trigger_instance) except: LOG.exception('No Trace found for TriggerInstance %s.', self.trigger_instance.id) return None # This would signify some sort of coding error so assert. assert trace_db trace_db = trace_service.add_or_update_given_trace_db( trace_db=trace_db, rules=[str(self.rule.id)]) return vars( TraceContext(id_=str(trace_db.id), trace_tag=trace_db.trace_tag))
def create_request(liveaction): """ Create an action execution. :return: (liveaction, execution) :rtype: tuple """ # Use the user context from the parent action execution. Subtasks in a workflow # action can be invoked by a system user and so we want to use the user context # from the original workflow action. parent_context = executions.get_parent_context(liveaction) if parent_context: parent_user = parent_context.get('user', None) if parent_user: liveaction.context['user'] = parent_user # Validate action. action_db = action_utils.get_action_by_ref(liveaction.action) if not action_db: raise ValueError('Action "%s" cannot be found.' % liveaction.action) if not action_db.enabled: raise ValueError('Unable to execute. Action "%s" is disabled.' % liveaction.action) runnertype_db = action_utils.get_runnertype_by_name( action_db.runner_type['name']) if not hasattr(liveaction, 'parameters'): liveaction.parameters = dict() # Validate action parameters. schema = util_schema.get_schema_for_action_parameters(action_db) validator = util_schema.get_validator() util_schema.validate(liveaction.parameters, schema, validator, use_default=True, allow_default_none=True) # validate that no immutable params are being overriden. Although possible to # ignore the override it is safer to inform the user to avoid surprises. immutables = _get_immutable_params(action_db.parameters) immutables.extend(_get_immutable_params(runnertype_db.runner_parameters)) overridden_immutables = [ p for p in six.iterkeys(liveaction.parameters) if p in immutables ] if len(overridden_immutables) > 0: raise ValueError( 'Override of immutable parameter(s) %s is unsupported.' % str(overridden_immutables)) # Set notification settings for action. # XXX: There are cases when we don't want notifications to be sent for a particular # execution. So we should look at liveaction.parameters['notify'] # and not set liveaction.notify. if not _is_notify_empty(action_db.notify): liveaction.notify = action_db.notify # Write to database and send to message queue. liveaction.status = action_constants.LIVEACTION_STATUS_REQUESTED liveaction.start_timestamp = date_utils.get_datetime_utc_now() # Set the "action_is_workflow" attribute liveaction.action_is_workflow = action_db.is_workflow() # Publish creation after both liveaction and actionexecution are created. liveaction = LiveAction.add_or_update(liveaction, publish=False) # Get trace_db if it exists. This could throw. If it throws, we have to cleanup # liveaction object so we don't see things in requested mode. trace_db = None try: _, trace_db = trace_service.get_trace_db_by_live_action(liveaction) except db_exc.StackStormDBObjectNotFoundError as e: _cleanup_liveaction(liveaction) raise trace_exc.TraceNotFoundException(str(e)) execution = executions.create_execution_object(liveaction, publish=False) if trace_db: trace_service.add_or_update_given_trace_db( trace_db=trace_db, action_executions=[ trace_service.get_trace_component_for_action_execution( execution, liveaction) ]) return liveaction, execution
def request(liveaction): """ Request an action execution. :return: (liveaction, execution) :rtype: tuple """ # Use the user context from the parent action execution. Subtasks in a workflow # action can be invoked by a system user and so we want to use the user context # from the original workflow action. if getattr(liveaction, 'context', None) and 'parent' in liveaction.context: parent_user = liveaction.context['parent'].get('user', None) if parent_user: liveaction.context['user'] = parent_user # Validate action. action_db = action_utils.get_action_by_ref(liveaction.action) if not action_db: raise ValueError('Action "%s" cannot be found.' % liveaction.action) if not action_db.enabled: raise ValueError('Unable to execute. Action "%s" is disabled.' % liveaction.action) runnertype_db = action_utils.get_runnertype_by_name(action_db.runner_type['name']) if not hasattr(liveaction, 'parameters'): liveaction.parameters = dict() # Validate action parameters. schema = util_schema.get_parameter_schema(action_db) validator = util_schema.get_validator() util_schema.validate(liveaction.parameters, schema, validator, use_default=True) # validate that no immutable params are being overriden. Although possible to # ignore the override it is safer to inform the user to avoid surprises. immutables = _get_immutable_params(action_db.parameters) immutables.extend(_get_immutable_params(runnertype_db.runner_parameters)) overridden_immutables = [p for p in six.iterkeys(liveaction.parameters) if p in immutables] if len(overridden_immutables) > 0: raise ValueError('Override of immutable parameter(s) %s is unsupported.' % str(overridden_immutables)) # Set notification settings for action. # XXX: There are cases when we don't want notifications to be sent for a particular # execution. So we should look at liveaction.parameters['notify'] # and not set liveaction.notify. if action_db.notify: liveaction.notify = action_db.notify # Write to database and send to message queue. liveaction.status = action_constants.LIVEACTION_STATUS_REQUESTED liveaction.start_timestamp = date_utils.get_datetime_utc_now() # Publish creation after both liveaction and actionexecution are created. liveaction = LiveAction.add_or_update(liveaction, publish=False) # Get trace_db if it exists. This could throw. If it throws, we have to cleanup # liveaction object so we don't see things in requested mode. trace_db = None try: _, trace_db = trace_service.get_trace_db_by_live_action(liveaction) except StackStormDBObjectNotFoundError as e: _cleanup_liveaction(liveaction) raise TraceNotFoundException(str(e)) execution = executions.create_execution_object(liveaction, publish=False) if trace_db: trace_service.add_or_update_given_trace_db( trace_db=trace_db, action_executions=[str(execution.id)]) # Assume that this is a creation. LiveAction.publish_create(liveaction) LiveAction.publish_status(liveaction) ActionExecution.publish_create(execution) extra = {'liveaction_db': liveaction, 'execution_db': execution} LOG.audit('Action execution requested. LiveAction.id=%s, ActionExecution.id=%s' % (liveaction.id, execution.id), extra=extra) return liveaction, execution
def create_request(liveaction, action_db=None, runnertype_db=None): """ Create an action execution. :param action_db: Action model to operate one. If not provided, one is retrieved from the database using values from "liveaction". :type action_db: :class:`ActionDB` :param runnertype_db: Runner model to operate one. If not provided, one is retrieved from the database using values from "liveaction". :type runnertype_db: :class:`RunnerTypeDB` :return: (liveaction, execution) :rtype: tuple """ # We import this here to avoid conflicts w/ runners that might import this # file since the runners don't have the config context by default. from st2common.metrics.base import get_driver # Use the user context from the parent action execution. Subtasks in a workflow # action can be invoked by a system user and so we want to use the user context # from the original workflow action. parent_context = executions.get_parent_context(liveaction) or {} parent_user = parent_context.get("user", None) if parent_user: liveaction.context["user"] = parent_user # Validate action if not action_db: action_db = action_utils.get_action_by_ref(liveaction.action) if not action_db: raise ValueError('Action "%s" cannot be found.' % liveaction.action) if not action_db.enabled: raise ValueError('Unable to execute. Action "%s" is disabled.' % liveaction.action) if not runnertype_db: runnertype_db = action_utils.get_runnertype_by_name( action_db.runner_type["name"]) if not hasattr(liveaction, "parameters"): liveaction.parameters = dict() # For consistency add pack to the context here in addition to RunnerContainer.dispatch() method liveaction.context["pack"] = action_db.pack # Validate action parameters. schema = util_schema.get_schema_for_action_parameters( action_db, runnertype_db) validator = util_schema.get_validator() util_schema.validate( liveaction.parameters, schema, validator, use_default=True, allow_default_none=True, ) # validate that no immutable params are being overriden. Although possible to # ignore the override it is safer to inform the user to avoid surprises. immutables = _get_immutable_params(action_db.parameters) immutables.extend(_get_immutable_params(runnertype_db.runner_parameters)) overridden_immutables = [ p for p in six.iterkeys(liveaction.parameters) if p in immutables ] if len(overridden_immutables) > 0: raise ValueError( "Override of immutable parameter(s) %s is unsupported." % str(overridden_immutables)) # Set notification settings for action. # XXX: There are cases when we don't want notifications to be sent for a particular # execution. So we should look at liveaction.parameters['notify'] # and not set liveaction.notify. if not _is_notify_skipped(liveaction) and not _is_notify_empty( action_db.notify): liveaction.notify = action_db.notify # Write to database and send to message queue. liveaction.status = action_constants.LIVEACTION_STATUS_REQUESTED liveaction.start_timestamp = date_utils.get_datetime_utc_now() # Set the "action_is_workflow" attribute liveaction.action_is_workflow = action_db.is_workflow() # Publish creation after both liveaction and actionexecution are created. liveaction = LiveAction.add_or_update(liveaction, publish=False) # Get trace_db if it exists. This could throw. If it throws, we have to cleanup # liveaction object so we don't see things in requested mode. trace_db = None try: _, trace_db = trace_service.get_trace_db_by_live_action(liveaction) except db_exc.StackStormDBObjectNotFoundError as e: _cleanup_liveaction(liveaction) raise trace_exc.TraceNotFoundException(six.text_type(e)) execution = executions.create_execution_object( liveaction=liveaction, action_db=action_db, runnertype_db=runnertype_db, publish=False, ) if trace_db: trace_service.add_or_update_given_trace_db( trace_db=trace_db, action_executions=[ trace_service.get_trace_component_for_action_execution( execution, liveaction) ], ) get_driver().inc_counter("action.executions.%s" % (liveaction.status)) return liveaction, execution
def create_request(liveaction, action_db=None, runnertype_db=None): """ Create an action execution. :param action_db: Action model to operate one. If not provided, one is retrieved from the database using values from "liveaction". :type action_db: :class:`ActionDB` :param runnertype_db: Runner model to operate one. If not provided, one is retrieved from the database using values from "liveaction". :type runnertype_db: :class:`RunnerTypeDB` :return: (liveaction, execution) :rtype: tuple """ # We import this here to avoid conflicts w/ runners that might import this # file since the runners don't have the config context by default. from st2common.metrics.base import get_driver # Use the user context from the parent action execution. Subtasks in a workflow # action can be invoked by a system user and so we want to use the user context # from the original workflow action. parent_context = executions.get_parent_context(liveaction) or {} parent_user = parent_context.get('user', None) if parent_user: liveaction.context['user'] = parent_user # Validate action if not action_db: action_db = action_utils.get_action_by_ref(liveaction.action) if not action_db: raise ValueError('Action "%s" cannot be found.' % liveaction.action) if not action_db.enabled: raise ValueError('Unable to execute. Action "%s" is disabled.' % liveaction.action) if not runnertype_db: runnertype_db = action_utils.get_runnertype_by_name(action_db.runner_type['name']) if not hasattr(liveaction, 'parameters'): liveaction.parameters = dict() # For consistency add pack to the context here in addition to RunnerContainer.dispatch() method liveaction.context['pack'] = action_db.pack # Validate action parameters. schema = util_schema.get_schema_for_action_parameters(action_db, runnertype_db) validator = util_schema.get_validator() util_schema.validate(liveaction.parameters, schema, validator, use_default=True, allow_default_none=True) # validate that no immutable params are being overriden. Although possible to # ignore the override it is safer to inform the user to avoid surprises. immutables = _get_immutable_params(action_db.parameters) immutables.extend(_get_immutable_params(runnertype_db.runner_parameters)) overridden_immutables = [p for p in six.iterkeys(liveaction.parameters) if p in immutables] if len(overridden_immutables) > 0: raise ValueError('Override of immutable parameter(s) %s is unsupported.' % str(overridden_immutables)) # Set notification settings for action. # XXX: There are cases when we don't want notifications to be sent for a particular # execution. So we should look at liveaction.parameters['notify'] # and not set liveaction.notify. if not _is_notify_empty(action_db.notify): liveaction.notify = action_db.notify # Write to database and send to message queue. liveaction.status = action_constants.LIVEACTION_STATUS_REQUESTED liveaction.start_timestamp = date_utils.get_datetime_utc_now() # Set the "action_is_workflow" attribute liveaction.action_is_workflow = action_db.is_workflow() # Publish creation after both liveaction and actionexecution are created. liveaction = LiveAction.add_or_update(liveaction, publish=False) # Get trace_db if it exists. This could throw. If it throws, we have to cleanup # liveaction object so we don't see things in requested mode. trace_db = None try: _, trace_db = trace_service.get_trace_db_by_live_action(liveaction) except db_exc.StackStormDBObjectNotFoundError as e: _cleanup_liveaction(liveaction) raise trace_exc.TraceNotFoundException(six.text_type(e)) execution = executions.create_execution_object(liveaction=liveaction, action_db=action_db, runnertype_db=runnertype_db, publish=False) if trace_db: trace_service.add_or_update_given_trace_db( trace_db=trace_db, action_executions=[ trace_service.get_trace_component_for_action_execution(execution, liveaction) ]) get_driver().inc_counter('action.executions.%s' % (liveaction.status)) return liveaction, execution