def enforce(self): # TODO: Refactor this to avoid additiona lookup in cast_params # TODO: rename self.rule.action -> self.rule.action_exec_spec action_ref = self.rule.action['ref'] action_db = action_db_util.get_action_by_ref(action_ref) if not action_db: raise ValueError('Action "%s" doesn\'t exist' % (action_ref)) data = self.data_transformer(self.rule.action.parameters) LOG.info('Invoking action %s for trigger_instance %s with data %s.', self.rule.action.ref, self.trigger_instance.id, json.dumps(data)) context = { 'trigger_instance': reference.get_ref_from_model(self.trigger_instance), 'rule': reference.get_ref_from_model(self.rule), 'user': get_system_username() } liveaction_db = RuleEnforcer._invoke_action(self.rule.action, data, context) if not liveaction_db: extra = {'trigger_instance_db': self.trigger_instance, 'rule_db': self.rule} LOG.audit('Rule enforcement failed. Liveaction for Action %s failed. ' 'TriggerInstance: %s and Rule: %s', self.rule.action.name, self.trigger_instance, self.rule, extra=extra) return None extra = {'trigger_instance_db': self.trigger_instance, 'rule_db': self.rule, 'liveaction_db': liveaction_db} LOG.audit('Rule enforced. Liveaction %s, TriggerInstance %s and Rule %s.', liveaction_db, self.trigger_instance, self.rule, extra=extra) return liveaction_db
def enforce(self): data = self.data_transformer(self.rule.action.parameters) LOG.info('Invoking action %s for trigger_instance %s with data %s.', self.rule.action.ref, self.trigger_instance.id, json.dumps(data)) context = { 'trigger_instance': reference.get_ref_from_model(self.trigger_instance), 'rule': reference.get_ref_from_model(self.rule), 'user': get_system_username() } liveaction = RuleEnforcer._invoke_action(self.rule.action, data, context) if not liveaction: LOG.audit( 'Rule enforcement failed. liveaction for Action %s failed. ' 'TriggerInstance: %s and Rule: %s', self.rule.action.name, self.trigger_instance, self.rule) return None liveaction_db = liveaction.get('id', None) LOG.audit( 'Rule enforced. liveaction %s, TriggerInstance %s and Rule %s.', liveaction_db, self.trigger_instance, self.rule) return liveaction_db
def test_to_reference_no_model_id(self): try: model = copy.copy(self.__model) model.id = None reference.get_ref_from_model(model) self.assertTrue(False, 'Exception expected.') except db.StackStormDBObjectMalformedError: self.assertTrue(True)
def enforce(self): # TODO: Refactor this to avoid additiona lookup in cast_params # TODO: rename self.rule.action -> self.rule.action_exec_spec action_ref = self.rule.action['ref'] action_db = action_db_util.get_action_by_ref(action_ref) if not action_db: raise ValueError('Action "%s" doesn\'t exist' % (action_ref)) data = self.data_transformer(self.rule.action.parameters) LOG.info('Invoking action %s for trigger_instance %s with data %s.', self.rule.action.ref, self.trigger_instance.id, json.dumps(data)) # update trace before invoking the action. trace_context = self._update_trace() LOG.debug('Updated trace %s with rule %s.', trace_context, self.rule.id) context = { 'trigger_instance': reference.get_ref_from_model(self.trigger_instance), 'rule': reference.get_ref_from_model(self.rule), 'user': get_system_username(), TRACE_CONTEXT: trace_context } liveaction_db = RuleEnforcer._invoke_action(self.rule.action, data, context) if not liveaction_db: extra = { 'trigger_instance_db': self.trigger_instance, 'rule_db': self.rule } LOG.audit( 'Rule enforcement failed. Liveaction for Action %s failed. ' 'TriggerInstance: %s and Rule: %s', self.rule.action.name, self.trigger_instance, self.rule, extra=extra) return None extra = { 'trigger_instance_db': self.trigger_instance, 'rule_db': self.rule, 'liveaction_db': liveaction_db } LOG.audit( 'Rule enforced. Liveaction %s, TriggerInstance %s and Rule %s.', liveaction_db, self.trigger_instance, self.rule, extra=extra) return liveaction_db
def enforce(self): # TODO: Refactor this to avoid additional lookup in cast_params # TODO: rename self.rule.action -> self.rule.action_exec_spec action_ref = self.rule.action['ref'] action_db = action_db_util.get_action_by_ref(action_ref) if not action_db: raise ValueError('Action "%s" doesn\'t exist' % (action_ref)) data = self.data_transformer(self.rule.action.parameters) LOG.info('Invoking action %s for trigger_instance %s with data %s.', self.rule.action.ref, self.trigger_instance.id, json.dumps(data)) # update trace before invoking the action. trace_context = self._update_trace() LOG.debug('Updated trace %s with rule %s.', trace_context, self.rule.id) context = { 'trigger_instance': reference.get_ref_from_model(self.trigger_instance), 'rule': reference.get_ref_from_model(self.rule), 'user': get_system_username(), TRACE_CONTEXT: trace_context } extra = {'trigger_instance_db': self.trigger_instance, 'rule_db': self.rule} rule_spec = {'ref': self.rule.ref, 'id': str(self.rule.id), 'uid': self.rule.uid} enforcement_db = RuleEnforcementDB(trigger_instance_id=str(self.trigger_instance.id), rule=rule_spec) try: execution_db = RuleEnforcer._invoke_action(self.rule.action, data, context) # pylint: disable=no-member enforcement_db.execution_id = str(execution_db.id) # pylint: enable=no-member except: LOG.exception('Failed kicking off execution for rule %s.', self.rule, extra=extra) return None finally: self._update_enforcement(enforcement_db) extra['execution_db'] = execution_db # pylint: disable=no-member if execution_db.status not in EXEC_KICKED_OFF_STATES: # pylint: enable=no-member LOG.audit('Rule enforcement failed. Execution of Action %s failed. ' 'TriggerInstance: %s and Rule: %s', self.rule.action.name, self.trigger_instance, self.rule, extra=extra) return execution_db LOG.audit('Rule enforced. Execution %s, TriggerInstance %s and Rule %s.', execution_db, self.trigger_instance, self.rule, extra=extra) return execution_db
def get_action_execution_context(self, action_db, trace_context=None): context = { "trigger_instance": reference.get_ref_from_model(self.trigger_instance), "rule": reference.get_ref_from_model(self.rule), "user": get_system_username(), "pack": action_db.pack, } if trace_context is not None: context[TRACE_CONTEXT] = trace_context # Additional non-action / global context additional_context = {TRIGGER_PAYLOAD_PREFIX: self.trigger_instance.payload} return context, additional_context
def _schedule_execution(self, action_alias_db, params, notify, context): action_ref = action_alias_db.action_ref action_db = action_utils.get_action_by_ref(action_ref) if not action_db: raise StackStormDBObjectNotFoundError('Action with ref "%s" not found ' % (action_ref)) assert_request_user_has_resource_db_permission(request=pecan.request, resource_db=action_db, permission_type=PermissionType.ACTION_EXECUTE) try: # prior to shipping off the params cast them to the right type. params = action_param_utils.cast_params(action_ref=action_alias_db.action_ref, params=params, cast_overrides=CAST_OVERRIDES) if not context: context = { 'action_alias_ref': reference.get_ref_from_model(action_alias_db), 'user': get_system_username() } liveaction = LiveActionDB(action=action_alias_db.action_ref, context=context, parameters=params, notify=notify) _, action_execution_db = action_service.request(liveaction) return ActionExecutionAPI.from_model(action_execution_db) except ValueError as e: LOG.exception('Unable to execute action.') pecan.abort(http_client.BAD_REQUEST, str(e)) except jsonschema.ValidationError as e: LOG.exception('Unable to execute action. Parameter validation failed.') pecan.abort(http_client.BAD_REQUEST, str(e)) except Exception as e: LOG.exception('Unable to execute action. Unexpected error encountered.') pecan.abort(http_client.INTERNAL_SERVER_ERROR, str(e))
def _schedule_execution(self, action_alias_db, params, notify, context): try: # prior to shipping off the params cast them to the right type. params = action_param_utils.cast_params( action_ref=action_alias_db.action_ref, params=params, cast_overrides=CAST_OVERRIDES) if not context: context = { 'action_alias_ref': reference.get_ref_from_model(action_alias_db), 'user': get_system_username() } liveaction = LiveActionDB(action=action_alias_db.action_ref, context=context, parameters=params, notify=notify) _, action_execution_db = action_service.request(liveaction) return action_execution_db except ValueError as e: LOG.exception('Unable to execute action.') pecan.abort(http_client.BAD_REQUEST, str(e)) except jsonschema.ValidationError as e: LOG.exception( 'Unable to execute action. Parameter validation failed.') pecan.abort(http_client.BAD_REQUEST, str(e)) except Exception as e: LOG.exception( 'Unable to execute action. Unexpected error encountered.') pecan.abort(http_client.INTERNAL_SERVER_ERROR, str(e))
def _schedule_execution(self, action_alias_db, params, notify, context, requester_user, show_secrets): action_ref = action_alias_db.action_ref action_db = action_utils.get_action_by_ref(action_ref) if not action_db: raise StackStormDBObjectNotFoundError('Action with ref "%s" not found ' % (action_ref)) assert_user_has_resource_db_permission(user_db=requester_user, resource_db=action_db, permission_type=PermissionType.ACTION_EXECUTE) try: # prior to shipping off the params cast them to the right type. params = action_param_utils.cast_params(action_ref=action_alias_db.action_ref, params=params, cast_overrides=CAST_OVERRIDES) if not context: context = { 'action_alias_ref': reference.get_ref_from_model(action_alias_db), 'user': get_system_username() } liveaction = LiveActionDB(action=action_alias_db.action_ref, context=context, parameters=params, notify=notify) _, action_execution_db = action_service.request(liveaction) mask_secrets = self._get_mask_secrets(requester_user, show_secrets=show_secrets) return ActionExecutionAPI.from_model(action_execution_db, mask_secrets=mask_secrets) except ValueError as e: LOG.exception('Unable to execute action.') abort(http_client.BAD_REQUEST, str(e)) except jsonschema.ValidationError as e: LOG.exception('Unable to execute action. Parameter validation failed.') abort(http_client.BAD_REQUEST, str(e)) except Exception as e: LOG.exception('Unable to execute action. Unexpected error encountered.') abort(http_client.INTERNAL_SERVER_ERROR, str(e))
def get_action_execution_context(self, action_db, trace_context=None): context = { 'trigger_instance': reference.get_ref_from_model(self.trigger_instance), 'rule': reference.get_ref_from_model(self.rule), 'user': get_system_username(), 'pack': action_db.pack, } if trace_context is not None: context[TRACE_CONTEXT] = trace_context # Additional non-action / global context additional_context = { TRIGGER_PAYLOAD_PREFIX: self.trigger_instance.payload } return context, additional_context
def post(self, payload): action_alias_name = payload.name if payload else None if not action_alias_name: pecan.abort(http_client.BAD_REQUEST, 'Alias execution "name" is required') format_str = payload.format or '' command = payload.command or '' try: action_alias_db = ActionAlias.get_by_name(action_alias_name) except ValueError: action_alias_db = None if not action_alias_db: msg = 'Unable to identify action alias with name "%s".' % ( action_alias_name) pecan.abort(http_client.NOT_FOUND, msg) return if not action_alias_db.enabled: msg = 'Action alias with name "%s" is disabled.' % ( action_alias_name) pecan.abort(http_client.BAD_REQUEST, msg) return execution_parameters = self._extract_parameters( action_alias_db=action_alias_db, format_str=format_str, param_stream=command) notify = self._get_notify_field(payload) context = { 'action_alias_ref': reference.get_ref_from_model(action_alias_db), 'api_user': payload.user, 'user': get_requester(), 'source_channel': payload.source_channel } execution = self._schedule_execution(action_alias_db=action_alias_db, params=execution_parameters, notify=notify, context=context) result = { 'execution': execution, 'actionalias': ActionAliasAPI.from_model(action_alias_db) } if action_alias_db.ack and 'format' in action_alias_db.ack: result.update({ 'message': render({'alias': action_alias_db.ack['format']}, result)['alias'] }) return result
def post(self, payload): action_alias_name = payload.name if payload else None if not action_alias_name: pecan.abort(http_client.BAD_REQUEST, 'Alias execution "name" is required') format_str = payload.format or '' command = payload.command or '' try: action_alias_db = ActionAlias.get_by_name(action_alias_name) except ValueError: action_alias_db = None if not action_alias_db: msg = 'Unable to identify action alias with name "%s".' % (action_alias_name) pecan.abort(http_client.NOT_FOUND, msg) return if not action_alias_db.enabled: msg = 'Action alias with name "%s" is disabled.' % (action_alias_name) pecan.abort(http_client.BAD_REQUEST, msg) return execution_parameters = extract_parameters_for_action_alias_db( action_alias_db=action_alias_db, format_str=format_str, param_stream=command) notify = self._get_notify_field(payload) context = { 'action_alias_ref': reference.get_ref_from_model(action_alias_db), 'api_user': payload.user, 'user': get_requester(), 'source_channel': payload.source_channel } execution = self._schedule_execution(action_alias_db=action_alias_db, params=execution_parameters, notify=notify, context=context) result = { 'execution': execution, 'actionalias': ActionAliasAPI.from_model(action_alias_db) } if action_alias_db.ack: if 'format' in action_alias_db.ack: result.update({ 'message': render({'alias': action_alias_db.ack['format']}, result)['alias'] }) if 'extra' in action_alias_db.ack: result.update({ 'extra': render(action_alias_db.ack['extra'], result) }) return result
def _do_enforce(self): params = self.get_resolved_parameters() LOG.info('Invoking action %s for trigger_instance %s with params %s.', self.rule.action.ref, self.trigger_instance.id, json.dumps(params)) # update trace before invoking the action. trace_context = self._update_trace() LOG.debug('Updated trace %s with rule %s.', trace_context, self.rule.id) context = { 'trigger_instance': reference.get_ref_from_model(self.trigger_instance), 'rule': reference.get_ref_from_model(self.rule), 'user': get_system_username(), TRACE_CONTEXT: trace_context } return RuleEnforcer._invoke_action(self.rule.action, params, context)
def setUpClass(cls): super(EnforceTest, cls).setUpClass() # Create TriggerTypes before creation of Rule to avoid failure. Rule requires the # Trigger and therefore TriggerType to be created prior to rule creation. cls.models = FixturesLoader().save_fixtures_to_db( fixtures_pack=PACK, fixtures_dict=FIXTURES_1) cls.models.update(FixturesLoader().save_fixtures_to_db( fixtures_pack=PACK, fixtures_dict=FIXTURES_2)) MOCK_TRIGGER_INSTANCE.trigger = reference.get_ref_from_model( cls.models['triggers']['trigger1.yaml'])
def enforce(self): data = self.data_transformer(self.rule.action.parameters) LOG.info('Invoking action %s for trigger_instance %s with data %s.', self.rule.action.ref, self.trigger_instance.id, json.dumps(data)) context = { 'trigger_instance': reference.get_ref_from_model(self.trigger_instance), 'rule': reference.get_ref_from_model(self.rule), 'user': get_system_username() } action_execution = RuleEnforcer._invoke_action(self.rule.action, data, context) if not action_execution: LOG.audit('Rule enforcement failed. ActionExecution for Action %s failed. ' 'TriggerInstance: %s and Rule: %s', self.rule.action.name, self.trigger_instance, self.rule) return None actionexecution_db = action_execution.get('id', None) LOG.audit('Rule enforced. ActionExecution %s, TriggerInstance %s and Rule %s.', actionexecution_db, self.trigger_instance, self.rule) return actionexecution_db
def post(self, payload): action_alias_name = payload.name if payload else None if not action_alias_name: pecan.abort(http_client.BAD_REQUEST, 'Alias execution "name" is required') format_str = payload.format or '' command = payload.command or '' try: action_alias_db = ActionAlias.get_by_name(action_alias_name) except ValueError: action_alias_db = None if not action_alias_db: msg = 'Unable to identify action alias with name "%s".' % (action_alias_name) pecan.abort(http_client.NOT_FOUND, msg) return if not action_alias_db.enabled: msg = 'Action alias with name "%s" is disabled.' % (action_alias_name) pecan.abort(http_client.BAD_REQUEST, msg) return execution_parameters = self._extract_parameters(action_alias_db=action_alias_db, format_str=format_str, param_stream=command) notify = self._get_notify_field(payload) context = { 'action_alias_ref': reference.get_ref_from_model(action_alias_db), 'api_user': payload.user, 'user': get_system_username(), 'source_channel': payload.source_channel } execution = self._schedule_execution(action_alias_db=action_alias_db, params=execution_parameters, notify=notify, context=context) return str(execution.id)
def _schedule_execution(self, action_alias_db, params, notify): try: # prior to shipping off the params cast them to the right type. params = action_param_utils.cast_params(action_ref=action_alias_db.action_ref, params=params, cast_overrides=CAST_OVERRIDES) context = { 'action_alias_ref': reference.get_ref_from_model(action_alias_db), 'user': get_system_username() } liveaction = LiveActionDB(action=action_alias_db.action_ref, context=context, parameters=params, notify=notify) _, action_execution_db = action_service.request(liveaction) return action_execution_db except ValueError as e: LOG.exception('Unable to execute action.') pecan.abort(http_client.BAD_REQUEST, str(e)) except jsonschema.ValidationError as e: LOG.exception('Unable to execute action. Parameter validation failed.') pecan.abort(http_client.BAD_REQUEST, str(e)) except Exception as e: LOG.exception('Unable to execute action. Unexpected error encountered.') pecan.abort(http_client.INTERNAL_SERVER_ERROR, str(e))
from st2common.models.db.reactor import TriggerDB, TriggerInstanceDB, \ RuleDB, ActionExecutionSpecDB from st2common.models.db.action import ActionDB, ActionExecutionDB import st2common.services.action as action_service from st2common.util import reference from st2reactor.rules.enforcer import RuleEnforcer import st2tests.config as tests_config MOCK_TRIGGER = TriggerDB() MOCK_TRIGGER.id = 'trigger-test.id' MOCK_TRIGGER.name = 'trigger-test.name' MOCK_TRIGGER.pack = 'dummypack1' MOCK_TRIGGER_INSTANCE = TriggerInstanceDB() MOCK_TRIGGER_INSTANCE.id = 'triggerinstance-test' MOCK_TRIGGER_INSTANCE.trigger = reference.get_ref_from_model(MOCK_TRIGGER) MOCK_TRIGGER_INSTANCE.payload = {} MOCK_TRIGGER_INSTANCE.occurrence_time = datetime.datetime.utcnow() MOCK_ACTION = ActionDB() MOCK_ACTION.id = 'action-test-1.id' MOCK_ACTION.name = 'action-test-1.name' MOCK_ACTION_EXECUTION = ActionExecutionDB() MOCK_ACTION_EXECUTION.id = 'actionexec-test-1.id' MOCK_ACTION_EXECUTION.name = 'actionexec-test-1.name' MOCK_ACTION_EXECUTION.status = 'scheduled' MOCK_RULE_1 = RuleDB() MOCK_RULE_1.id = 'rule-test-1' MOCK_RULE_1.trigger = reference.get_str_resource_ref_from_model(MOCK_TRIGGER)
def test_to_reference(self): ref = reference.get_ref_from_model(self.__model) self.assertEqual(ref, self.__ref, 'Failed to generated equivalent ref.')
def test_to_reference_no_model(self): try: reference.get_ref_from_model(None) self.assertTrue(False, 'Exception expected.') except ValueError: self.assertTrue(True)
def _post(self, payload, requester_user, show_secrets=False, match_multiple=False): action_alias_name = payload.name if payload else None if not action_alias_name: abort(http_client.BAD_REQUEST, 'Alias execution "name" is required') return if not requester_user: requester_user = UserDB(cfg.CONF.system_user.user) format_str = payload.format or '' command = payload.command or '' try: action_alias_db = ActionAlias.get_by_name(action_alias_name) except ValueError: action_alias_db = None if not action_alias_db: msg = 'Unable to identify action alias with name "%s".' % ( action_alias_name) abort(http_client.NOT_FOUND, msg) return if not action_alias_db.enabled: msg = 'Action alias with name "%s" is disabled.' % ( action_alias_name) abort(http_client.BAD_REQUEST, msg) return if match_multiple: multiple_execution_parameters = extract_parameters_for_action_alias_db( action_alias_db=action_alias_db, format_str=format_str, param_stream=command, match_multiple=match_multiple) else: multiple_execution_parameters = [ extract_parameters_for_action_alias_db( action_alias_db=action_alias_db, format_str=format_str, param_stream=command, match_multiple=match_multiple) ] notify = self._get_notify_field(payload) context = { 'action_alias_ref': reference.get_ref_from_model(action_alias_db), 'api_user': payload.user, 'user': requester_user.name, 'source_channel': payload.source_channel, } inject_immutable_parameters( action_alias_db=action_alias_db, multiple_execution_parameters=multiple_execution_parameters, action_context=context) results = [] for execution_parameters in multiple_execution_parameters: execution = self._schedule_execution( action_alias_db=action_alias_db, params=execution_parameters, notify=notify, context=context, show_secrets=show_secrets, requester_user=requester_user) result = { 'execution': execution, 'actionalias': ActionAliasAPI.from_model(action_alias_db) } if action_alias_db.ack: try: if 'format' in action_alias_db.ack: message = render( {'alias': action_alias_db.ack['format']}, result)['alias'] result.update({'message': message}) except UndefinedError as e: result.update({ 'message': ('Cannot render "format" in field "ack" for alias. ' + six.text_type(e)) }) try: if 'extra' in action_alias_db.ack: result.update({ 'extra': render(action_alias_db.ack['extra'], result) }) except UndefinedError as e: result.update({ 'extra': ('Cannot render "extra" in field "ack" for alias. ' + six.text_type(e)) }) results.append(result) return results
def post(self, payload, requester_user=None, show_secrets=False): action_alias_name = payload.name if payload else None if not action_alias_name: abort(http_client.BAD_REQUEST, 'Alias execution "name" is required') return if not requester_user: requester_user = UserDB(cfg.CONF.system_user.user) format_str = payload.format or '' command = payload.command or '' try: action_alias_db = ActionAlias.get_by_name(action_alias_name) except ValueError: action_alias_db = None if not action_alias_db: msg = 'Unable to identify action alias with name "%s".' % ( action_alias_name) abort(http_client.NOT_FOUND, msg) return if not action_alias_db.enabled: msg = 'Action alias with name "%s" is disabled.' % ( action_alias_name) abort(http_client.BAD_REQUEST, msg) return execution_parameters = extract_parameters_for_action_alias_db( action_alias_db=action_alias_db, format_str=format_str, param_stream=command) notify = self._get_notify_field(payload) context = { 'action_alias_ref': reference.get_ref_from_model(action_alias_db), 'api_user': payload.user, 'user': requester_user.name, 'source_channel': payload.source_channel } execution = self._schedule_execution(action_alias_db=action_alias_db, params=execution_parameters, notify=notify, context=context, show_secrets=show_secrets, requester_user=requester_user) result = { 'execution': execution, 'actionalias': ActionAliasAPI.from_model(action_alias_db) } if action_alias_db.ack: try: if 'format' in action_alias_db.ack: result.update({ 'message': render({'alias': action_alias_db.ack['format']}, result)['alias'] }) except UndefinedError as e: result.update({ 'message': 'Cannot render "format" in field "ack" for alias. ' + e.message }) try: if 'extra' in action_alias_db.ack: result.update({ 'extra': render(action_alias_db.ack['extra'], result) }) except UndefinedError as e: result.update({ 'extra': 'Cannot render "extra" in field "ack" for alias. ' + e.message }) return Response(json=result, status=http_client.CREATED)
def enforce(self): params = self.get_resolved_parameters() LOG.info('Invoking action %s for trigger_instance %s with params %s.', self.rule.action.ref, self.trigger_instance.id, json.dumps(params)) # update trace before invoking the action. trace_context = self._update_trace() LOG.debug('Updated trace %s with rule %s.', trace_context, self.rule.id) context = { 'trigger_instance': reference.get_ref_from_model(self.trigger_instance), 'rule': reference.get_ref_from_model(self.rule), 'user': get_system_username(), TRACE_CONTEXT: trace_context } extra = { 'trigger_instance_db': self.trigger_instance, 'rule_db': self.rule } rule_spec = { 'ref': self.rule.ref, 'id': str(self.rule.id), 'uid': self.rule.uid } enforcement_db = RuleEnforcementDB(trigger_instance_id=str( self.trigger_instance.id), rule=rule_spec) try: execution_db = RuleEnforcer._invoke_action(self.rule.action, params, context) # pylint: disable=no-member enforcement_db.execution_id = str(execution_db.id) # pylint: enable=no-member except: LOG.exception('Failed kicking off execution for rule %s.', self.rule, extra=extra) return None finally: self._update_enforcement(enforcement_db) extra['execution_db'] = execution_db # pylint: disable=no-member if execution_db.status not in EXEC_KICKED_OFF_STATES: # pylint: enable=no-member LOG.audit( 'Rule enforcement failed. Execution of Action %s failed. ' 'TriggerInstance: %s and Rule: %s', self.rule.action.name, self.trigger_instance, self.rule, extra=extra) return execution_db LOG.audit( 'Rule enforced. Execution %s, TriggerInstance %s and Rule %s.', execution_db, self.trigger_instance, self.rule, extra=extra) return execution_db
def _post(self, payload, requester_user, show_secrets=False, match_multiple=False): action_alias_name = payload.name if payload else None if not action_alias_name: abort(http_client.BAD_REQUEST, 'Alias execution "name" is required') return if not requester_user: requester_user = UserDB(cfg.CONF.system_user.user) format_str = payload.format or '' command = payload.command or '' try: action_alias_db = ActionAlias.get_by_name(action_alias_name) except ValueError: action_alias_db = None if not action_alias_db: msg = 'Unable to identify action alias with name "%s".' % (action_alias_name) abort(http_client.NOT_FOUND, msg) return if not action_alias_db.enabled: msg = 'Action alias with name "%s" is disabled.' % (action_alias_name) abort(http_client.BAD_REQUEST, msg) return if match_multiple: multiple_execution_parameters = extract_parameters_for_action_alias_db( action_alias_db=action_alias_db, format_str=format_str, param_stream=command, match_multiple=match_multiple) else: multiple_execution_parameters = [ extract_parameters_for_action_alias_db( action_alias_db=action_alias_db, format_str=format_str, param_stream=command, match_multiple=match_multiple) ] notify = self._get_notify_field(payload) context = { 'action_alias_ref': reference.get_ref_from_model(action_alias_db), 'api_user': payload.user, 'user': requester_user.name, 'source_channel': payload.source_channel } results = [] for execution_parameters in multiple_execution_parameters: execution = self._schedule_execution(action_alias_db=action_alias_db, params=execution_parameters, notify=notify, context=context, show_secrets=show_secrets, requester_user=requester_user) result = { 'execution': execution, 'actionalias': ActionAliasAPI.from_model(action_alias_db) } if action_alias_db.ack: try: if 'format' in action_alias_db.ack: message = render({'alias': action_alias_db.ack['format']}, result)['alias'] result.update({ 'message': message }) except UndefinedError as e: result.update({ 'message': ('Cannot render "format" in field "ack" for alias. ' + six.text_type(e)) }) try: if 'extra' in action_alias_db.ack: result.update({ 'extra': render(action_alias_db.ack['extra'], result) }) except UndefinedError as e: result.update({ 'extra': ('Cannot render "extra" in field "ack" for alias. ' + six.text_type(e)) }) results.append(result) return results
def enforce(self): # TODO: Refactor this to avoid additional lookup in cast_params # TODO: rename self.rule.action -> self.rule.action_exec_spec action_ref = self.rule.action['ref'] action_db = action_db_util.get_action_by_ref(action_ref) if not action_db: raise ValueError('Action "%s" doesn\'t exist' % (action_ref)) data = self.data_transformer(self.rule.action.parameters) LOG.info('Invoking action %s for trigger_instance %s with data %s.', self.rule.action.ref, self.trigger_instance.id, json.dumps(data)) # update trace before invoking the action. trace_context = self._update_trace() LOG.debug('Updated trace %s with rule %s.', trace_context, self.rule.id) context = { 'trigger_instance': reference.get_ref_from_model(self.trigger_instance), 'rule': reference.get_ref_from_model(self.rule), 'user': get_system_username(), TRACE_CONTEXT: trace_context } extra = { 'trigger_instance_db': self.trigger_instance, 'rule_db': self.rule } rule_spec = { 'ref': self.rule.ref, 'id': str(self.rule.id), 'uid': self.rule.uid } enforcement_db = RuleEnforcementDB(trigger_instance_id=str( self.trigger_instance.id), rule=rule_spec) try: execution_db = RuleEnforcer._invoke_action(self.rule.action, data, context) # pylint: disable=no-member enforcement_db.execution_id = str(execution_db.id) # pylint: enable=no-member except: LOG.exception('Failed kicking off execution for rule %s.', self.rule, extra=extra) return None finally: self._update_enforcement(enforcement_db) extra['execution_db'] = execution_db # pylint: disable=no-member if execution_db.status not in EXEC_KICKED_OFF_STATES: # pylint: enable=no-member LOG.audit( 'Rule enforcement failed. Execution of Action %s failed. ' 'TriggerInstance: %s and Rule: %s', self.rule.action.name, self.trigger_instance, self.rule, extra=extra) return execution_db LOG.audit( 'Rule enforced. Execution %s, TriggerInstance %s and Rule %s.', execution_db, self.trigger_instance, self.rule, extra=extra) return execution_db