def create_execution_object(liveaction, action_db=None, runnertype_db=None, publish=True): if not action_db: action_db = action_utils.get_action_by_ref(liveaction.action) if not runnertype_db: runnertype_db = RunnerType.get_by_name(action_db.runner_type['name']) attrs = { 'action': vars(ActionAPI.from_model(action_db)), 'parameters': liveaction['parameters'], 'runner': vars(RunnerTypeAPI.from_model(runnertype_db)) } attrs.update(_decompose_liveaction(liveaction)) if 'rule' in liveaction.context: rule = reference.get_model_from_ref(Rule, liveaction.context.get('rule', {})) attrs['rule'] = vars(RuleAPI.from_model(rule)) if 'trigger_instance' in liveaction.context: trigger_instance_id = liveaction.context.get('trigger_instance', {}) trigger_instance_id = trigger_instance_id.get('id', None) trigger_instance = TriggerInstance.get_by_id(trigger_instance_id) trigger = reference.get_model_by_resource_ref(db_api=Trigger, ref=trigger_instance.trigger) trigger_type = reference.get_model_by_resource_ref(db_api=TriggerType, ref=trigger.type) trigger_instance = reference.get_model_from_ref( TriggerInstance, liveaction.context.get('trigger_instance', {})) attrs['trigger_instance'] = vars(TriggerInstanceAPI.from_model(trigger_instance)) attrs['trigger'] = vars(TriggerAPI.from_model(trigger)) attrs['trigger_type'] = vars(TriggerTypeAPI.from_model(trigger_type)) parent = _get_parent_execution(liveaction) if parent: attrs['parent'] = str(parent.id) attrs['log'] = [_create_execution_log_entry(liveaction['status'])] # TODO: This object initialization takes 20-30or so ms execution = ActionExecutionDB(**attrs) # TODO: Do 100% research this is fully safe and unique in distributed setups execution.id = ObjectId() execution.web_url = _get_web_url_for_execution(str(execution.id)) # NOTE: User input data is already validate as part of the API request, # other data is set by us. Skipping validation here makes operation 10%-30% faster execution = ActionExecution.add_or_update(execution, publish=publish, validate=False) if parent and str(execution.id) not in parent.children: values = {} values['push__children'] = str(execution.id) ActionExecution.update(parent, **values) return execution
def create_execution_object(liveaction, publish=True): action_db = action_utils.get_action_by_ref(liveaction.action) runner = RunnerType.get_by_name(action_db.runner_type['name']) attrs = { 'action': vars(ActionAPI.from_model(action_db)), 'parameters': liveaction['parameters'], 'runner': vars(RunnerTypeAPI.from_model(runner)) } attrs.update(_decompose_liveaction(liveaction)) if 'rule' in liveaction.context: rule = reference.get_model_from_ref(Rule, liveaction.context.get('rule', {})) attrs['rule'] = vars(RuleAPI.from_model(rule)) if 'trigger_instance' in liveaction.context: trigger_instance_id = liveaction.context.get('trigger_instance', {}) trigger_instance_id = trigger_instance_id.get('id', None) trigger_instance = TriggerInstance.get_by_id(trigger_instance_id) trigger = reference.get_model_by_resource_ref( db_api=Trigger, ref=trigger_instance.trigger) trigger_type = reference.get_model_by_resource_ref(db_api=TriggerType, ref=trigger.type) trigger_instance = reference.get_model_from_ref( TriggerInstance, liveaction.context.get('trigger_instance', {})) attrs['trigger_instance'] = vars( TriggerInstanceAPI.from_model(trigger_instance)) attrs['trigger'] = vars(TriggerAPI.from_model(trigger)) attrs['trigger_type'] = vars(TriggerTypeAPI.from_model(trigger_type)) parent = _get_parent_execution(liveaction) if parent: attrs['parent'] = str(parent.id) attrs['log'] = [_create_execution_log_entry(liveaction['status'])] execution = ActionExecutionDB(**attrs) execution = ActionExecution.add_or_update(execution, publish=False) # Update the web_url field in execution. Unfortunately, we need # the execution id for constructing the URL which we only get # after the model is written to disk. execution.web_url = _get_web_url_for_execution(str(execution.id)) execution = ActionExecution.add_or_update(execution, publish=publish) if parent: if str(execution.id) not in parent.children: parent.children.append(str(execution.id)) ActionExecution.add_or_update(parent) return execution
def create_execution_object(liveaction, publish=True): action_db = action_utils.get_action_by_ref(liveaction.action) runner = RunnerType.get_by_name(action_db.runner_type['name']) attrs = { 'action': vars(ActionAPI.from_model(action_db)), 'parameters': liveaction['parameters'], 'runner': vars(RunnerTypeAPI.from_model(runner)) } attrs.update(_decompose_liveaction(liveaction)) if 'rule' in liveaction.context: rule = reference.get_model_from_ref(Rule, liveaction.context.get('rule', {})) attrs['rule'] = vars(RuleAPI.from_model(rule)) if 'trigger_instance' in liveaction.context: trigger_instance_id = liveaction.context.get('trigger_instance', {}) trigger_instance_id = trigger_instance_id.get('id', None) trigger_instance = TriggerInstance.get_by_id(trigger_instance_id) trigger = reference.get_model_by_resource_ref(db_api=Trigger, ref=trigger_instance.trigger) trigger_type = reference.get_model_by_resource_ref(db_api=TriggerType, ref=trigger.type) trigger_instance = reference.get_model_from_ref( TriggerInstance, liveaction.context.get('trigger_instance', {})) attrs['trigger_instance'] = vars(TriggerInstanceAPI.from_model(trigger_instance)) attrs['trigger'] = vars(TriggerAPI.from_model(trigger)) attrs['trigger_type'] = vars(TriggerTypeAPI.from_model(trigger_type)) parent = _get_parent_execution(liveaction) if parent: attrs['parent'] = str(parent.id) attrs['log'] = [_create_execution_log_entry(liveaction['status'])] execution = ActionExecutionDB(**attrs) execution = ActionExecution.add_or_update(execution, publish=False) # Update the web_url field in execution. Unfortunately, we need # the execution id for constructing the URL which we only get # after the model is written to disk. execution.web_url = _get_web_url_for_execution(str(execution.id)) execution = ActionExecution.add_or_update(execution, publish=publish) if parent: if str(execution.id) not in parent.children: parent.children.append(str(execution.id)) ActionExecution.add_or_update(parent) return execution
def test_garbage_collection(self): now = date_utils.get_datetime_utc_now() status = action_constants.LIVEACTION_STATUS_SUCCEEDED # Insert come mock ActionExecutionDB objects with start_timestamp < TTL defined in the # config old_executions_count = 15 ttl_days = 30 timestamp = (now - datetime.timedelta(days=ttl_days)) for index in range(0, old_executions_count): action_execution_db = ActionExecutionDB( start_timestamp=timestamp, end_timestamp=timestamp, status=status, action={'ref': 'core.local'}, runner={'name': 'run-local'}, liveaction={'ref': 'foo'}) ActionExecution.add_or_update(action_execution_db) # Insert come mock ActionExecutionDB objects with start_timestamp > TTL defined in the # config new_executions_count = 5 ttl_days = 2 timestamp = (now - datetime.timedelta(days=ttl_days)) for index in range(0, new_executions_count): action_execution_db = ActionExecutionDB( start_timestamp=timestamp, end_timestamp=timestamp, status=status, action={'ref': 'core.local'}, runner={'name': 'run-local'}, liveaction={'ref': 'foo'}) ActionExecution.add_or_update(action_execution_db) execs = ActionExecution.get_all() self.assertEqual(len(execs), (old_executions_count + new_executions_count)) # Start garbage collector process = self._start_garbage_collector() # Give it some time to perform garbage collection and kill it eventlet.sleep(5) process.send_signal(signal.SIGKILL) self.remove_process(process=process) # Old execution should have been garbage collected execs = ActionExecution.get_all() self.assertEqual(len(execs), (new_executions_count))
def test_execution_secret_parameter(self, request): execution = ActionExecutionDB( id="54e657d60640fd16887d6855", status=LIVEACTION_STATUS_SUCCEEDED, action={"parameters": self.action1.parameters}, runner={"runner_parameters": self.runner1.runner_parameters}, parameters={"param4": SUPER_SECRET_PARAMETER}, result="", ) request.return_value = (None, execution) command = "Lorem ipsum value1 dolor sit " + SUPER_SECRET_PARAMETER + " amet." post_resp = self._do_post(alias_execution=self.alias4, command=command) self.assertEqual(post_resp.status_int, 201) expected_parameters = {"param1": "value1", "param4": SUPER_SECRET_PARAMETER} self.assertEqual(request.call_args[0][0].parameters, expected_parameters) post_resp = self._do_post( alias_execution=self.alias4, command=command, show_secrets=True, expect_errors=True, ) self.assertEqual(post_resp.status_int, 201) self.assertEqual( post_resp.json["execution"]["parameters"]["param4"], SUPER_SECRET_PARAMETER )
def test_execution_secret_parameter(self, request): execution = ActionExecutionDB( id='54e657d60640fd16887d6855', status=LIVEACTION_STATUS_SUCCEEDED, action={'parameters': self.action1.parameters}, runner={'runner_parameters': self.runner1.runner_parameters}, parameters={'param4': SUPER_SECRET_PARAMETER}, result='') request.return_value = (None, execution) command = 'Lorem ipsum value1 dolor sit ' + SUPER_SECRET_PARAMETER + ' amet.' post_resp = self._do_post(alias_execution=self.alias4, command=command) self.assertEqual(post_resp.status_int, 201) expected_parameters = { 'param1': 'value1', 'param4': SUPER_SECRET_PARAMETER } self.assertEquals(request.call_args[0][0].parameters, expected_parameters) post_resp = self._do_post(alias_execution=self.alias4, command=command, show_secrets=True, expect_errors=True) self.assertEqual(post_resp.status_int, 201) self.assertEqual(post_resp.json['execution']['parameters']['param4'], SUPER_SECRET_PARAMETER)
def test_get_output_finished_execution(self): # Test the execution output API endpoint for execution which has finished for status in action_constants.LIVEACTION_COMPLETED_STATES: # Insert mock execution and output objects status = action_constants.LIVEACTION_STATUS_SUCCEEDED timestamp = date_utils.get_datetime_utc_now() action_execution_db = ActionExecutionDB( start_timestamp=timestamp, end_timestamp=timestamp, status=status, action={"ref": "core.local"}, runner={"name": "local-shell-cmd"}, liveaction={"ref": "foo"}, ) action_execution_db = ActionExecution.add_or_update( action_execution_db) for i in range(1, 6): stdout_db = ActionExecutionOutputDB( execution_id=str(action_execution_db.id), action_ref="core.local", runner_ref="dummy", timestamp=timestamp, output_type="stdout", data="stdout %s\n" % (i), ) ActionExecutionOutput.add_or_update(stdout_db) for i in range(10, 15): stderr_db = ActionExecutionOutputDB( execution_id=str(action_execution_db.id), action_ref="core.local", runner_ref="dummy", timestamp=timestamp, output_type="stderr", data="stderr %s\n" % (i), ) ActionExecutionOutput.add_or_update(stderr_db) resp = self.app.get( "/v1/executions/%s/output" % (str(action_execution_db.id)), expect_errors=False, ) self.assertEqual(resp.status_int, 200) events = self._parse_response(resp.text) self.assertEqual(len(events), 11) self.assertEqual(events[0][1]["data"], "stdout 1\n") self.assertEqual(events[9][1]["data"], "stderr 14\n") self.assertEqual(events[10][0], "EOF") # Verify "last" short-hand id works resp = self.app.get("/v1/executions/last/output", expect_errors=False) self.assertEqual(resp.status_int, 200) events = self._parse_response(resp.text) self.assertEqual(len(events), 11) self.assertEqual(events[10][0], "EOF")
def test_get_output_finished_execution(self): # Test the execution output API endpoint for execution which has finished for status in action_constants.LIVEACTION_COMPLETED_STATES: # Insert mock execution and output objects status = action_constants.LIVEACTION_STATUS_SUCCEEDED timestamp = date_utils.get_datetime_utc_now() action_execution_db = ActionExecutionDB( start_timestamp=timestamp, end_timestamp=timestamp, status=status, action={'ref': 'core.local'}, runner={'name': 'local-shell-cmd'}, liveaction={'ref': 'foo'}) action_execution_db = ActionExecution.add_or_update( action_execution_db) for i in range(1, 6): stdout_db = ActionExecutionOutputDB(execution_id=str( action_execution_db.id), action_ref='core.local', runner_ref='dummy', timestamp=timestamp, output_type='stdout', data='stdout %s\n' % (i)) ActionExecutionOutput.add_or_update(stdout_db) for i in range(10, 15): stderr_db = ActionExecutionOutputDB(execution_id=str( action_execution_db.id), action_ref='core.local', runner_ref='dummy', timestamp=timestamp, output_type='stderr', data='stderr %s\n' % (i)) ActionExecutionOutput.add_or_update(stderr_db) resp = self.app.get('/v1/executions/%s/output' % (str(action_execution_db.id)), expect_errors=False) self.assertEqual(resp.status_int, 200) events = self._parse_response(resp.text) self.assertEqual(len(events), 11) self.assertEqual(events[0][1]['data'], 'stdout 1\n') self.assertEqual(events[9][1]['data'], 'stderr 14\n') self.assertEqual(events[10][0], 'EOF') # Verify "last" short-hand id works resp = self.app.get('/v1/executions/last/output', expect_errors=False) self.assertEqual(resp.status_int, 200) events = self._parse_response(resp.text) self.assertEqual(len(events), 11) self.assertEqual(events[10][0], 'EOF')
def setUp(self): created = ActionExecutionDB() created.action = {'uid': 'action:core:ask'} created.status = 'succeeded' created.runner = {'name': 'inquirer'} created.liveaction = INQUIRY_LIVEACTION created.result = INQUIRY_RESULT self.saved = ActionExecutionModelTest._save_execution(created) self.retrieved = ActionExecution.get_by_id(self.saved.id) self.assertEqual(self.saved.action, self.retrieved.action, 'Same action was not returned.')
def test_format_secret_action_parameters_are_masked(self): formatter = ConsoleLogFormatter() mock_message = 'test message 1' mock_action_db = ActionDB() mock_action_db.name = 'test.action' mock_action_db.pack = 'testpack' mock_action_db.parameters = { 'parameter1': { 'type': 'string', 'required': False }, 'parameter2': { 'type': 'string', 'required': False, 'secret': True } } mock_action_execution_db = ActionExecutionDB() mock_action_execution_db.action = mock_action_db.to_serializable_dict() mock_action_execution_db.parameters = { 'parameter1': 'value1', 'parameter2': 'value2' } record = MockRecord() record.msg = mock_message # Add "extra" attributes record._action_execution_db = mock_action_execution_db expected_msg_part = "'parameters': {'parameter1': 'value1', 'parameter2': '********'}" message = formatter.format(record=record) self.assertTrue('test message 1' in message) self.assertTrue(expected_msg_part in message)
def create_execution_object(liveaction, publish=True): action_db = action_utils.get_action_by_ref(liveaction.action) runner = RunnerType.get_by_name(action_db.runner_type['name']) attrs = { 'action': vars(ActionAPI.from_model(action_db)), 'runner': vars(RunnerTypeAPI.from_model(runner)) } attrs.update(_decompose_liveaction(liveaction)) if 'rule' in liveaction.context: rule = reference.get_model_from_ref(Rule, liveaction.context.get('rule', {})) attrs['rule'] = vars(RuleAPI.from_model(rule)) if 'trigger_instance' in liveaction.context: trigger_instance_id = liveaction.context.get('trigger_instance', {}) trigger_instance_id = trigger_instance_id.get('id', None) trigger_instance = TriggerInstance.get_by_id(trigger_instance_id) trigger = reference.get_model_by_resource_ref( db_api=Trigger, ref=trigger_instance.trigger) trigger_type = reference.get_model_by_resource_ref(db_api=TriggerType, ref=trigger.type) trigger_instance = reference.get_model_from_ref( TriggerInstance, liveaction.context.get('trigger_instance', {})) attrs['trigger_instance'] = vars( TriggerInstanceAPI.from_model(trigger_instance)) attrs['trigger'] = vars(TriggerAPI.from_model(trigger)) attrs['trigger_type'] = vars(TriggerTypeAPI.from_model(trigger_type)) parent = ActionExecution.get( liveaction__id=liveaction.context.get('parent', '')) if parent: attrs['parent'] = str(parent.id) execution = ActionExecutionDB(**attrs) execution = ActionExecution.add_or_update(execution, publish=publish) if parent: if str(execution.id) not in parent.children: parent.children.append(str(execution.id)) ActionExecution.add_or_update(parent) return execution
def setUp(self): self.executions = {} for name, execution in ACTIONEXECUTIONS.items(): created = ActionExecutionDB() created.action = execution['action'] created.status = execution['status'] created.runner = execution['runner'] created.liveaction = execution['liveaction'] created.result = execution['result'] saved = ActionExecutionModelTest._save_execution(created) retrieved = ActionExecution.get_by_id(saved.id) self.assertEqual(saved.action, retrieved.action, 'Same action was not returned.') self.executions[name] = retrieved
def test_format_secret_action_parameters_are_masked(self): formatter = ConsoleLogFormatter() mock_message = 'test message 1' parameters = { 'parameter1': { 'type': 'string', 'required': False }, 'parameter2': { 'type': 'string', 'required': False, 'secret': True } } mock_action_db = ActionDB(pack='testpack', name='test.action', parameters=parameters) action = mock_action_db.to_serializable_dict() parameters = {'parameter1': 'value1', 'parameter2': 'value2'} mock_action_execution_db = ActionExecutionDB(action=action, parameters=parameters) record = MockRecord() record.msg = mock_message # Add "extra" attributes record._action_execution_db = mock_action_execution_db expected_msg_part = (r"'parameters': {u?'parameter1': u?'value1', " r"u?'parameter2': u?'\*\*\*\*\*\*\*\*'}") message = formatter.format(record=record) self.assertTrue('test message 1' in message) self.assertRegexpMatches(message, expected_msg_part)
from st2common.models.db.execution import ActionExecutionDB from st2common.models.db.liveaction import LiveActionDB from st2common.models.db.notification import NotificationSchema from st2common.models.db.notification import NotificationSubSchema from st2common.models.db.runner import RunnerTypeDB from st2common.persistence.action import Action from st2common.persistence.liveaction import LiveAction from st2common.persistence.policy import Policy from st2common.models.system.common import ResourceReference from st2common.util import date as date_utils from st2common.util import isotime from st2tests.base import CleanDbTestCase ACTION_TRIGGER_TYPE = INTERNAL_TRIGGER_TYPES['action'][0] NOTIFY_TRIGGER_TYPE = INTERNAL_TRIGGER_TYPES['action'][1] MOCK_EXECUTION = ActionExecutionDB(id=bson.ObjectId(), result={'stdout': 'stuff happens'}) class NotifierTestCase(CleanDbTestCase): class MockDispatcher(object): def __init__(self, tester): self.tester = tester self.notify_trigger = ResourceReference.to_string_reference( pack=NOTIFY_TRIGGER_TYPE['pack'], name=NOTIFY_TRIGGER_TYPE['name']) self.action_trigger = ResourceReference.to_string_reference( pack=ACTION_TRIGGER_TYPE['pack'], name=ACTION_TRIGGER_TYPE['name']) def dispatch(self, *args, **kwargs): try:
def test_get_all_with_filters(self): cfg.CONF.set_override(name='heartbeat', group='stream', override=0.1) listener = st2common.stream.listener.get_listener(name='stream') process_execution = listener.processor(ActionExecutionAPI) process_liveaction = listener.processor(LiveActionAPI) process_output = listener.processor(ActionExecutionOutputAPI) process_no_api_model = listener.processor() execution_api = ActionExecutionDB(**EXECUTION_1) liveaction_api = LiveActionDB(**LIVE_ACTION_1) output_api_stdout = ActionExecutionOutputDB(**STDOUT_1) output_api_stderr = ActionExecutionOutputDB(**STDERR_1) def dispatch_and_handle_mock_data(resp): received_messages_data = '' for index, message in enumerate(resp._app_iter): if message.strip(): received_messages_data += message # Dispatch some mock events if index == 0: meta = META('st2.execution', 'create') process_execution(execution_api, meta) elif index == 1: meta = META('st2.execution', 'update') process_execution(execution_api, meta) elif index == 2: meta = META('st2.execution', 'delete') process_execution(execution_api, meta) elif index == 3: meta = META('st2.liveaction', 'create') process_liveaction(liveaction_api, meta) elif index == 4: meta = META('st2.liveaction', 'create') process_liveaction(liveaction_api, meta) elif index == 5: meta = META('st2.liveaction', 'delete') process_liveaction(liveaction_api, meta) elif index == 6: meta = META('st2.liveaction', 'delete') process_liveaction(liveaction_api, meta) elif index == 7: meta = META('st2.announcement', 'chatops') process_no_api_model({}, meta) elif index == 8: meta = META('st2.execution.output', 'create') process_output(output_api_stdout, meta) elif index == 9: meta = META('st2.execution.output', 'create') process_output(output_api_stderr, meta) elif index == 10: meta = META('st2.announcement', 'errbot') process_no_api_model({}, meta) else: break received_messages = received_messages_data.split('\n\n') received_messages = [message for message in received_messages if message] return received_messages # 1. Default filter - stdout and stderr messages should be excluded for backward # compatibility reasons resp = stream.StreamController().get_all() received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 9) self.assertTrue('st2.execution__create' in received_messages[0]) self.assertTrue('st2.liveaction__delete' in received_messages[5]) self.assertTrue('st2.announcement__chatops' in received_messages[7]) self.assertTrue('st2.announcement__errbot' in received_messages[8]) # 1. ?events= filter # No filter provided - all messages should be received stream.DEFAULT_EVENTS_WHITELIST = None resp = stream.StreamController().get_all() received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 11) self.assertTrue('st2.execution__create' in received_messages[0]) self.assertTrue('st2.announcement__chatops' in received_messages[7]) self.assertTrue('st2.execution.output__create' in received_messages[8]) self.assertTrue('st2.execution.output__create' in received_messages[9]) self.assertTrue('st2.announcement__errbot' in received_messages[10]) # Filter provided, only three messages should be received events = ['st2.execution__create', 'st2.liveaction__delete'] resp = stream.StreamController().get_all(events=events) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 3) self.assertTrue('st2.execution__create' in received_messages[0]) self.assertTrue('st2.liveaction__delete' in received_messages[1]) self.assertTrue('st2.liveaction__delete' in received_messages[2]) # Filter provided, only three messages should be received events = ['st2.liveaction__create', 'st2.liveaction__delete'] resp = stream.StreamController().get_all(events=events) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 4) self.assertTrue('st2.liveaction__create' in received_messages[0]) self.assertTrue('st2.liveaction__create' in received_messages[1]) self.assertTrue('st2.liveaction__delete' in received_messages[2]) self.assertTrue('st2.liveaction__delete' in received_messages[3]) # Glob filter events = ['st2.announcement__*'] resp = stream.StreamController().get_all(events=events) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 2) self.assertTrue('st2.announcement__chatops' in received_messages[0]) self.assertTrue('st2.announcement__errbot' in received_messages[1]) # Filter provided events = ['st2.execution.output__create'] resp = stream.StreamController().get_all(events=events) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 2) self.assertTrue('st2.execution.output__create' in received_messages[0]) self.assertTrue('st2.execution.output__create' in received_messages[1]) # Filter provided, invalid , no message should be received events = ['invalid1', 'invalid2'] resp = stream.StreamController().get_all(events=events) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 0) # 2. ?action_refs= filter action_refs = ['invalid1', 'invalid2'] resp = stream.StreamController().get_all(action_refs=action_refs) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 0) action_refs = ['dummy.action1'] resp = stream.StreamController().get_all(action_refs=action_refs) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 2) # 3. ?execution_ids= filter execution_ids = ['invalid1', 'invalid2'] resp = stream.StreamController().get_all(execution_ids=execution_ids) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 0) execution_ids = [EXECUTION_1['id']] resp = stream.StreamController().get_all(execution_ids=execution_ids) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 5)
FIXTURES_PACK = 'aliases' TEST_MODELS = { 'aliases': [ 'alias1.yaml', 'alias2.yaml', 'alias_with_undefined_jinja_in_ack_format.yaml', 'alias4.yaml', 'alias_fixes1.yaml', 'alias_fixes2.yaml', 'alias_match_multiple.yaml' ], 'actions': ['action1.yaml', 'action2.yaml'], 'runners': ['runner1.yaml'] } TEST_LOAD_MODELS = {'aliases': ['alias3.yaml']} EXECUTION = ActionExecutionDB(id='54e657d60640fd16887d6855', status=LIVEACTION_STATUS_SUCCEEDED, result='') __all__ = ['AliasExecutionTestCase'] class AliasExecutionTestCase(FunctionalTest): models = None alias1 = None alias2 = None alias_with_undefined_jinja_in_ack_format = None @classmethod def setUpClass(cls): super(AliasExecutionTestCase, cls).setUpClass()
MOCK_TRIGGER_INSTANCE_2 = TriggerInstanceDB() MOCK_TRIGGER_INSTANCE_2.id = 'triggerinstance-test2' MOCK_TRIGGER_INSTANCE_2.payload = {'t1_p': None} MOCK_TRIGGER_INSTANCE_2.occurrence_time = date_utils.get_datetime_utc_now() MOCK_TRIGGER_INSTANCE_3 = TriggerInstanceDB() MOCK_TRIGGER_INSTANCE_3.id = 'triggerinstance-test3' MOCK_TRIGGER_INSTANCE_3.payload = {'t1_p': None, 't2_p': 'value2'} MOCK_TRIGGER_INSTANCE_3.occurrence_time = date_utils.get_datetime_utc_now() MOCK_LIVEACTION = LiveActionDB() MOCK_LIVEACTION.id = 'liveaction-test-1.id' MOCK_LIVEACTION.status = 'requested' MOCK_EXECUTION = ActionExecutionDB() MOCK_EXECUTION.id = 'exec-test-1.id' MOCK_EXECUTION.status = 'requested' FAILURE_REASON = "fail!" class EnforceTest(DbTestCase): models = None @classmethod 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.
"k5": { "foo": "bar" }, "k6": [1, 3], } MOCK_TRIGGER_INSTANCE_4 = TriggerInstanceDB() MOCK_TRIGGER_INSTANCE_4.id = "triggerinstance-test4" MOCK_TRIGGER_INSTANCE_4.payload = MOCK_TRIGGER_INSTANCE_PAYLOAD MOCK_TRIGGER_INSTANCE_4.occurrence_time = date_utils.get_datetime_utc_now() MOCK_LIVEACTION = LiveActionDB() MOCK_LIVEACTION.id = "liveaction-test-1.id" MOCK_LIVEACTION.status = "requested" MOCK_EXECUTION = ActionExecutionDB() MOCK_EXECUTION.id = "exec-test-1.id" MOCK_EXECUTION.status = "requested" FAILURE_REASON = "fail!" class BaseRuleEnforcerTestCase(DbTestCase): models = None @classmethod def setUpClass(cls): super(BaseRuleEnforcerTestCase, cls).setUpClass() runners_registrar.register_runners()
def test_get_all_with_filters(self): cfg.CONF.set_override(name='heartbeat', group='stream', override=0.1) listener = st2stream.listener.get_listener() process_execution = listener.processor(ActionExecutionAPI) process_liveaction = listener.processor(LiveActionAPI) execution_api = ActionExecutionDB(**EXECUTION_1) liveaction_api = LiveActionDB(**LIVE_ACTION_1) liveaction_api_2 = LiveActionDB(**LIVE_ACTION_1) liveaction_api_2.action = 'dummy.action1' def dispatch_and_handle_mock_data(resp): received_messages_data = '' for index, message in enumerate(resp._app_iter): if message.strip(): received_messages_data += message # Dispatch some mock events if index == 0: meta = META('st2.execution', 'create') process_execution(execution_api, meta) elif index == 1: meta = META('st2.execution', 'update') process_execution(execution_api, meta) elif index == 2: meta = META('st2.execution', 'delete') process_execution(execution_api, meta) elif index == 3: meta = META('st2.liveaction', 'create') process_liveaction(liveaction_api, meta) elif index == 4: meta = META('st2.liveaction', 'create') process_liveaction(liveaction_api, meta) elif index == 5: meta = META('st2.liveaction', 'delete') process_liveaction(liveaction_api_2, meta) else: break received_messages = received_messages_data.split('\n\n') received_messages = [message for message in received_messages if message] return received_messages # 1. Default filter resp = stream.StreamController().get_all() received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 6) # 1. ?events= filter # No filter provided - all messages should be received resp = stream.StreamController().get_all() received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 6) # Filter provided, only two messages should be received events = ['st2.execution__create', 'st2.liveaction__delete'] events = ','.join(events) resp = stream.StreamController().get_all(events=events) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 2) # Filter provided, invalid , no message should be received events = ['invalid1', 'invalid2'] events = ','.join(events) resp = stream.StreamController().get_all(events=events) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 0) # 2. ?action_refs= filter action_refs = ['invalid1', 'invalid2'] action_refs = ','.join(action_refs) resp = stream.StreamController().get_all(action_refs=action_refs) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 0) action_refs = ['dummy.action1'] action_refs = ','.join(action_refs) resp = stream.StreamController().get_all(action_refs=action_refs) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 1) # 3. ?execution_ids= filter execution_ids = ['invalid1', 'invalid2'] execution_ids = ','.join(execution_ids) resp = stream.StreamController().get_all(execution_ids=execution_ids) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 0) execution_ids = [EXECUTION_1['id']] execution_ids = ','.join(execution_ids) resp = stream.StreamController().get_all(execution_ids=execution_ids) received_messages = dispatch_and_handle_mock_data(resp) self.assertEqual(len(received_messages), 3)
'state': MOCK_WF_EX_INCOMPLETE_TASKS_DATA[0]['state'], 'state_info': MOCK_WF_EX_INCOMPLETE_TASKS_DATA[0]['state_info'], 'input': json.loads(MOCK_WF_EX_INCOMPLETE_TASKS_DATA[0]['input']), 'result': json.loads(MOCK_WF_EX_INCOMPLETE_TASKS_DATA[0]['result']), 'published': json.loads(MOCK_WF_EX_INCOMPLETE_TASKS_DATA[0]['published']) }] } MOCK_CHILD_ACTIONEXECUTION_REQUESTED = ActionExecutionDB( action={'ref': 'mock.task'}, runner={'name': 'local-shell-cmd'}, liveaction={'id': uuid.uuid4().hex}, status=action_constants.LIVEACTION_STATUS_REQUESTED, children=[]) MOCK_CHILD_ACTIONEXECUTION_RUNNING = ActionExecutionDB( action={'ref': 'mock.task'}, runner={'name': 'local-shell-cmd'}, liveaction={'id': uuid.uuid4().hex}, status=action_constants.LIVEACTION_STATUS_RUNNING, children=[]) MOCK_CHILD_ACTIONEXECUTION_SUCCEEDED = ActionExecutionDB( action={'ref': 'mock.task'}, runner={'name': 'local-shell-cmd'}, liveaction={'id': uuid.uuid4().hex}, status=action_constants.LIVEACTION_STATUS_SUCCEEDED,
def test_garbage_collection(self): now = date_utils.get_datetime_utc_now() status = action_constants.LIVEACTION_STATUS_SUCCEEDED # Insert come mock ActionExecutionDB objects with start_timestamp < TTL defined in the # config old_executions_count = 15 ttl_days = 30 # > 20 timestamp = (now - datetime.timedelta(days=ttl_days)) for index in range(0, old_executions_count): action_execution_db = ActionExecutionDB( start_timestamp=timestamp, end_timestamp=timestamp, status=status, action={'ref': 'core.local'}, runner={'name': 'local-shell-cmd'}, liveaction={'ref': 'foo'}) ActionExecution.add_or_update(action_execution_db) stdout_db = ActionExecutionOutputDB(execution_id=str( action_execution_db.id), action_ref='core.local', runner_ref='dummy', timestamp=timestamp, output_type='stdout', data='stdout') ActionExecutionOutput.add_or_update(stdout_db) stderr_db = ActionExecutionOutputDB(execution_id=str( action_execution_db.id), action_ref='core.local', runner_ref='dummy', timestamp=timestamp, output_type='stderr', data='stderr') ActionExecutionOutput.add_or_update(stderr_db) # Insert come mock ActionExecutionDB objects with start_timestamp > TTL defined in the # config new_executions_count = 5 ttl_days = 2 # < 20 timestamp = (now - datetime.timedelta(days=ttl_days)) for index in range(0, new_executions_count): action_execution_db = ActionExecutionDB( start_timestamp=timestamp, end_timestamp=timestamp, status=status, action={'ref': 'core.local'}, runner={'name': 'local-shell-cmd'}, liveaction={'ref': 'foo'}) ActionExecution.add_or_update(action_execution_db) stdout_db = ActionExecutionOutputDB(execution_id=str( action_execution_db.id), action_ref='core.local', runner_ref='dummy', timestamp=timestamp, output_type='stdout', data='stdout') ActionExecutionOutput.add_or_update(stdout_db) stderr_db = ActionExecutionOutputDB(execution_id=str( action_execution_db.id), action_ref='core.local', runner_ref='dummy', timestamp=timestamp, output_type='stderr', data='stderr') ActionExecutionOutput.add_or_update(stderr_db) # Insert some mock output objects where start_timestamp > action_executions_output_ttl new_output_count = 5 ttl_days = 15 # > 10 and < 20 timestamp = (now - datetime.timedelta(days=ttl_days)) for index in range(0, new_output_count): action_execution_db = ActionExecutionDB( start_timestamp=timestamp, end_timestamp=timestamp, status=status, action={'ref': 'core.local'}, runner={'name': 'local-shell-cmd'}, liveaction={'ref': 'foo'}) ActionExecution.add_or_update(action_execution_db) stdout_db = ActionExecutionOutputDB(execution_id=str( action_execution_db.id), action_ref='core.local', runner_ref='dummy', timestamp=timestamp, output_type='stdout', data='stdout') ActionExecutionOutput.add_or_update(stdout_db) stderr_db = ActionExecutionOutputDB(execution_id=str( action_execution_db.id), action_ref='core.local', runner_ref='dummy', timestamp=timestamp, output_type='stderr', data='stderr') ActionExecutionOutput.add_or_update(stderr_db) execs = ActionExecution.get_all() self.assertEqual( len(execs), (old_executions_count + new_executions_count + new_output_count)) stdout_dbs = ActionExecutionOutput.query(output_type='stdout') self.assertEqual( len(stdout_dbs), (old_executions_count + new_executions_count + new_output_count)) stderr_dbs = ActionExecutionOutput.query(output_type='stderr') self.assertEqual( len(stderr_dbs), (old_executions_count + new_executions_count + new_output_count)) # Start garbage collector process = self._start_garbage_collector() # Give it some time to perform garbage collection and kill it eventlet.sleep(15) process.send_signal(signal.SIGKILL) self.remove_process(process=process) # Old executions and corresponding objects should have been garbage collected execs = ActionExecution.get_all() self.assertEqual(len(execs), (new_executions_count + new_output_count)) # Collection for output objects older than 10 days is also enabled, so those objects # should be deleted as well stdout_dbs = ActionExecutionOutput.query(output_type='stdout') self.assertEqual(len(stdout_dbs), (new_executions_count)) stderr_dbs = ActionExecutionOutput.query(output_type='stderr') self.assertEqual(len(stderr_dbs), (new_executions_count))
def setUp(self): super(InquiryPermissionsResolverTestCase, self).setUp() # Create some mock users user_1_db = UserDB(name='custom_role_inquiry_list_grant') user_1_db = User.add_or_update(user_1_db) self.users['custom_role_inquiry_list_grant'] = user_1_db user_2_db = UserDB(name='custom_role_inquiry_view_grant') user_2_db = User.add_or_update(user_2_db) self.users['custom_role_inquiry_view_grant'] = user_2_db user_3_db = UserDB(name='custom_role_inquiry_respond_grant') user_3_db = User.add_or_update(user_3_db) self.users['custom_role_inquiry_respond_grant'] = user_3_db user_4_db = UserDB(name='custom_role_inquiry_all_grant') user_4_db = User.add_or_update(user_4_db) self.users['custom_role_inquiry_all_grant'] = user_4_db user_5_db = UserDB(name='custom_role_inquiry_inherit') user_5_db = User.add_or_update(user_5_db) self.users['custom_role_inquiry_inherit'] = user_5_db # Create a workflow for testing inheritance of action_execute permission # to inquiry_respond permission wf_db = ActionDB(pack='examples', name='mistral-ask-basic', entry_point='', runner_type={'name': 'mistral-v2'}) wf_db = Action.add_or_update(wf_db) self.resources['wf'] = wf_db runner = {'name': 'mistral-v2'} liveaction = {'action': 'examples.mistral-ask-basic'} status = action_constants.LIVEACTION_STATUS_PAUSED # Spawn workflow action = {'uid': wf_db.get_uid(), 'pack': 'examples'} wf_exc_db = ActionExecutionDB(action=action, runner=runner, liveaction=liveaction, status=status) wf_exc_db = ActionExecution.add_or_update(wf_exc_db) # Create an Inquiry on which permissions can be granted action_1_db = ActionDB(pack='core', name='ask', entry_point='', runner_type={'name': 'inquirer'}) action_1_db = Action.add_or_update(action_1_db) self.resources['action_1'] = action_1_db runner = {'name': 'inquirer'} liveaction = {'action': 'core.ask'} status = action_constants.LIVEACTION_STATUS_PENDING # For now, Inquiries are "borrowing" the ActionExecutionDB model, # so we have to test with that model action = {'uid': action_1_db.get_uid(), 'pack': 'core'} inquiry_1_db = ActionExecutionDB(action=action, runner=runner, liveaction=liveaction, status=status) # A separate inquiry that has a parent (so we can test workflow permission inheritance) inquiry_2_db = ActionExecutionDB(action=action, runner=runner, liveaction=liveaction, status=status, parent=str(wf_exc_db.id)) # A bit gross, but it's what we have to do since Inquiries # don't yet have their own data model def get_uid(): return "inquiry" inquiry_1_db.get_uid = get_uid inquiry_2_db.get_uid = get_uid inquiry_1_db = ActionExecution.add_or_update(inquiry_1_db) inquiry_2_db = ActionExecution.add_or_update(inquiry_2_db) self.resources['inquiry_1'] = inquiry_1_db self.resources['inquiry_2'] = inquiry_2_db ############################################################ # Create some mock roles with associated permission grants # ############################################################ # Custom role - "inquiry_list" grant grant_db = PermissionGrantDB( resource_uid=self.resources['inquiry_1'].get_uid(), resource_type=ResourceType.INQUIRY, permission_types=[PermissionType.INQUIRY_LIST]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_inquiry_list_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_inquiry_list_grant'] = role_db # Custom role - "inquiry_view" grant grant_db = PermissionGrantDB( resource_uid=self.resources['inquiry_1'].get_uid(), resource_type=ResourceType.INQUIRY, permission_types=[PermissionType.INQUIRY_VIEW]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_inquiry_view_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_inquiry_view_grant'] = role_db # Custom role - "inquiry_respond" grant grant_db = PermissionGrantDB( resource_uid=self.resources['inquiry_1'].get_uid(), resource_type=ResourceType.INQUIRY, permission_types=[PermissionType.INQUIRY_RESPOND]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_inquiry_respond_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_inquiry_respond_grant'] = role_db # Custom role - "inquiry_all" grant grant_db = PermissionGrantDB( resource_uid=self.resources['inquiry_1'].get_uid(), resource_type=ResourceType.INQUIRY, permission_types=[PermissionType.INQUIRY_ALL]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_inquiry_all_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_inquiry_all_grant'] = role_db # Custom role - inheritance grant grant_db = PermissionGrantDB( resource_uid=self.resources['wf'].get_uid(), resource_type=ResourceType.ACTION, permission_types=[PermissionType.ACTION_EXECUTE]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_inquiry_inherit', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_inquiry_inherit'] = role_db ##################################### # Create some mock role assignments # ##################################### user_db = self.users['custom_role_inquiry_list_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_inquiry_list_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_inquiry_view_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_inquiry_view_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_inquiry_respond_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_inquiry_respond_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_inquiry_all_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_inquiry_all_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_inquiry_inherit'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_inquiry_inherit'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db)
def test_get_output_running_execution(self): # Retrieve lister instance to avoid race with listener connection not being established # early enough for tests to pass. # NOTE: This only affects tests where listeners are not pre-initialized. listener = get_listener(name='execution_output') eventlet.sleep(1.0) # Test the execution output API endpoint for execution which is running (blocking) status = action_constants.LIVEACTION_STATUS_RUNNING timestamp = date_utils.get_datetime_utc_now() action_execution_db = ActionExecutionDB( start_timestamp=timestamp, end_timestamp=timestamp, status=status, action={'ref': 'core.local'}, runner={'name': 'local-shell-cmd'}, liveaction={'ref': 'foo'}) action_execution_db = ActionExecution.add_or_update( action_execution_db) output_params = dict(execution_id=str(action_execution_db.id), action_ref='core.local', runner_ref='dummy', timestamp=timestamp, output_type='stdout', data='stdout before start\n') # Insert mock output object output_db = ActionExecutionOutputDB(**output_params) ActionExecutionOutput.add_or_update(output_db, publish=False) def insert_mock_data(): output_params['data'] = 'stdout mid 1\n' output_db = ActionExecutionOutputDB(**output_params) ActionExecutionOutput.add_or_update(output_db) # Since the API endpoint is blocking (connection is kept open until action finishes), we # spawn an eventlet which eventually finishes the action. def publish_action_finished(action_execution_db): # Insert mock output object output_params['data'] = 'stdout pre finish 1\n' output_db = ActionExecutionOutputDB(**output_params) ActionExecutionOutput.add_or_update(output_db) eventlet.sleep(1.0) # Transition execution to completed state so the connection closes action_execution_db.status = action_constants.LIVEACTION_STATUS_SUCCEEDED action_execution_db = ActionExecution.add_or_update( action_execution_db) eventlet.spawn_after(0.2, insert_mock_data) eventlet.spawn_after(1.5, publish_action_finished, action_execution_db) # Retrieve data while execution is running - endpoint return new data once it's available # and block until the execution finishes resp = self.app.get('/v1/executions/%s/output' % (str(action_execution_db.id)), expect_errors=False) self.assertEqual(resp.status_int, 200) events = self._parse_response(resp.text) self.assertEqual(len(events), 4) self.assertEqual(events[0][1]['data'], 'stdout before start\n') self.assertEqual(events[1][1]['data'], 'stdout mid 1\n') self.assertEqual(events[2][1]['data'], 'stdout pre finish 1\n') self.assertEqual(events[3][0], 'EOF') # Once the execution is in completed state, existing output should be returned immediately resp = self.app.get('/v1/executions/%s/output' % (str(action_execution_db.id)), expect_errors=False) self.assertEqual(resp.status_int, 200) events = self._parse_response(resp.text) self.assertEqual(len(events), 4) self.assertEqual(events[0][1]['data'], 'stdout before start\n') self.assertEqual(events[1][1]['data'], 'stdout mid 1\n') self.assertEqual(events[2][1]['data'], 'stdout pre finish 1\n') self.assertEqual(events[3][0], 'EOF') listener.shutdown()
def setUp(self): super(InquiryPermissionsResolverTestCase, self).setUp() # Create some mock users user_1_db = UserDB(name='custom_role_inquiry_list_grant') user_1_db = User.add_or_update(user_1_db) self.users['custom_role_inquiry_list_grant'] = user_1_db user_2_db = UserDB(name='custom_role_inquiry_view_grant') user_2_db = User.add_or_update(user_2_db) self.users['custom_role_inquiry_view_grant'] = user_2_db user_3_db = UserDB(name='custom_role_inquiry_respond_grant') user_3_db = User.add_or_update(user_3_db) self.users['custom_role_inquiry_respond_grant'] = user_3_db user_4_db = UserDB(name='custom_role_inquiry_all_grant') user_4_db = User.add_or_update(user_4_db) self.users['custom_role_inquiry_all_grant'] = user_4_db user_5_db = UserDB(name='custom_role_inquiry_inherit') user_5_db = User.add_or_update(user_5_db) self.users['custom_role_inquiry_inherit'] = user_5_db # Create a workflow for testing inheritance of action_execute permission # to inquiry_respond permission wf_db = ActionDB(pack='examples', name='mistral-ask-basic', entry_point='', runner_type={'name': 'mistral-v2'}) wf_db = Action.add_or_update(wf_db) self.resources['wf'] = wf_db runner = {'name': 'mistral-v2'} liveaction = {'action': 'examples.mistral-ask-basic'} status = action_constants.LIVEACTION_STATUS_PAUSED # Spawn workflow action = {'uid': wf_db.get_uid(), 'pack': 'examples'} wf_exc_db = ActionExecutionDB(action=action, runner=runner, liveaction=liveaction, status=status) wf_exc_db = ActionExecution.add_or_update(wf_exc_db) # Create an Inquiry on which permissions can be granted action_1_db = ActionDB(pack='core', name='ask', entry_point='', runner_type={'name': 'inquirer'}) action_1_db = Action.add_or_update(action_1_db) self.resources['action_1'] = action_1_db runner = {'name': 'inquirer'} liveaction = {'action': 'core.ask'} status = action_constants.LIVEACTION_STATUS_PENDING # For now, Inquiries are "borrowing" the ActionExecutionDB model, # so we have to test with that model action = {'uid': action_1_db.get_uid(), 'pack': 'core'} inquiry_1_db = ActionExecutionDB(action=action, runner=runner, liveaction=liveaction, status=status) # A separate inquiry that has a parent (so we can test workflow permission inheritance) inquiry_2_db = ActionExecutionDB(action=action, runner=runner, liveaction=liveaction, status=status, parent=str(wf_exc_db.id)) # A bit gross, but it's what we have to do since Inquiries # don't yet have their own data model def get_uid(): return "inquiry" inquiry_1_db.get_uid = get_uid inquiry_2_db.get_uid = get_uid inquiry_1_db = ActionExecution.add_or_update(inquiry_1_db) inquiry_2_db = ActionExecution.add_or_update(inquiry_2_db) self.resources['inquiry_1'] = inquiry_1_db self.resources['inquiry_2'] = inquiry_2_db ############################################################ # Create some mock roles with associated permission grants # ############################################################ # Custom role - "inquiry_list" grant grant_db = PermissionGrantDB(resource_uid=self.resources['inquiry_1'].get_uid(), resource_type=ResourceType.INQUIRY, permission_types=[PermissionType.INQUIRY_LIST]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_inquiry_list_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_inquiry_list_grant'] = role_db # Custom role - "inquiry_view" grant grant_db = PermissionGrantDB(resource_uid=self.resources['inquiry_1'].get_uid(), resource_type=ResourceType.INQUIRY, permission_types=[PermissionType.INQUIRY_VIEW]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_inquiry_view_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_inquiry_view_grant'] = role_db # Custom role - "inquiry_respond" grant grant_db = PermissionGrantDB(resource_uid=self.resources['inquiry_1'].get_uid(), resource_type=ResourceType.INQUIRY, permission_types=[PermissionType.INQUIRY_RESPOND]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_inquiry_respond_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_inquiry_respond_grant'] = role_db # Custom role - "inquiry_all" grant grant_db = PermissionGrantDB(resource_uid=self.resources['inquiry_1'].get_uid(), resource_type=ResourceType.INQUIRY, permission_types=[PermissionType.INQUIRY_ALL]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_inquiry_all_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_inquiry_all_grant'] = role_db # Custom role - inheritance grant grant_db = PermissionGrantDB(resource_uid=self.resources['wf'].get_uid(), resource_type=ResourceType.ACTION, permission_types=[PermissionType.ACTION_EXECUTE]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_inquiry_inherit', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_inquiry_inherit'] = role_db ##################################### # Create some mock role assignments # ##################################### user_db = self.users['custom_role_inquiry_list_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_inquiry_list_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_inquiry_view_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_inquiry_view_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_inquiry_respond_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_inquiry_respond_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_inquiry_all_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_inquiry_all_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_inquiry_inherit'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_inquiry_inherit'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db)
def test_get_output_running_execution(self): # Test the execution output API endpoint for execution which is running (blocking) status = action_constants.LIVEACTION_STATUS_RUNNING timestamp = date_utils.get_datetime_utc_now() action_execution_db = ActionExecutionDB(start_timestamp=timestamp, end_timestamp=timestamp, status=status, action={'ref': 'core.local'}, runner={'name': 'run-local'}, liveaction={'ref': 'foo'}) action_execution_db = ActionExecution.add_or_update(action_execution_db) output_params = dict(execution_id=str(action_execution_db.id), action_ref='core.local', runner_ref='dummy', timestamp=timestamp, output_type='stdout', data='stdout before start\n') # Insert mock output object output_db = ActionExecutionOutputDB(**output_params) ActionExecutionOutput.add_or_update(output_db) def insert_mock_data(): output_params['data'] = 'stdout mid 1\n' output_db = ActionExecutionOutputDB(**output_params) ActionExecutionOutput.add_or_update(output_db) pass # Since the API endpoint is blocking (connection is kept open until action finishes), we # spawn an eventlet which eventually finishes the action. def publish_action_finished(action_execution_db): # Insert mock output object output_params['data'] = 'stdout pre finish 1\n' output_db = ActionExecutionOutputDB(**output_params) ActionExecutionOutput.add_or_update(output_db) # Transition execution to completed state so the connection closes action_execution_db.status = action_constants.LIVEACTION_STATUS_SUCCEEDED action_execution_db = ActionExecution.add_or_update(action_execution_db) eventlet.spawn_after(0.2, insert_mock_data) eventlet.spawn_after(1.5, publish_action_finished, action_execution_db) resp = self.app.get('/v1/executions/%s/output' % (str(action_execution_db.id)), expect_errors=False) self.assertEqual(resp.status_int, 200) lines = resp.text.strip().split('\n') self.assertEqual(len(lines), 3) self.assertEqual(lines[0], 'stdout before start') self.assertEqual(lines[1], 'stdout mid 1') self.assertEqual(lines[2], 'stdout pre finish 1') # Once the execution is in completed state, existing output should be returned immediately resp = self.app.get('/v1/executions/%s/output' % (str(action_execution_db.id)), expect_errors=False) self.assertEqual(resp.status_int, 200) lines = resp.text.strip().split('\n') self.assertEqual(len(lines), 3) self.assertEqual(lines[0], 'stdout before start') self.assertEqual(lines[1], 'stdout mid 1') self.assertEqual(lines[2], 'stdout pre finish 1')
def setUp(self): super(ExecutionPermissionsResolverTestCase, self).setUp() # Create some mock users user_1_db = UserDB(name='custom_role_unrelated_pack_action_grant') user_1_db = User.add_or_update(user_1_db) self.users['custom_role_unrelated_pack_action_grant'] = user_1_db user_2_db = UserDB( name='custom_role_pack_action_grant_unrelated_permission') user_2_db = User.add_or_update(user_2_db) self.users[ 'custom_role_pack_action_grant_unrelated_permission'] = user_2_db user_3_db = UserDB(name='custom_role_pack_action_view_grant') user_3_db = User.add_or_update(user_3_db) self.users['custom_role_pack_action_view_grant'] = user_3_db user_4_db = UserDB(name='custom_role_action_view_grant') user_4_db = User.add_or_update(user_4_db) self.users['custom_role_action_view_grant'] = user_4_db user_5_db = UserDB(name='custom_role_pack_action_execute_grant') user_5_db = User.add_or_update(user_5_db) self.users['custom_role_pack_action_execute_grant'] = user_5_db user_6_db = UserDB(name='custom_role_action_execute_grant') user_6_db = User.add_or_update(user_6_db) self.users['custom_role_action_execute_grant'] = user_6_db user_7_db = UserDB(name='custom_role_pack_action_all_grant') user_7_db = User.add_or_update(user_7_db) self.users['custom_role_pack_action_all_grant'] = user_7_db user_8_db = UserDB(name='custom_role_action_all_grant') user_8_db = User.add_or_update(user_8_db) self.users['custom_role_action_all_grant'] = user_8_db user_9_db = UserDB(name='custom_role_execution_list_grant') user_9_db = User.add_or_update(user_5_db) self.users['custom_role_execution_list_grant'] = user_9_db # Create some mock resources on which permissions can be granted action_1_db = ActionDB(pack='test_pack_2', name='action1', entry_point='', runner_type={'name': 'run-local'}) action_1_db = Action.add_or_update(action_1_db) self.resources['action_1'] = action_1_db runner = {'name': 'run-python'} liveaction = {'action': 'test_pack_2.action1'} status = action_constants.LIVEACTION_STATUS_REQUESTED action = {'uid': action_1_db.get_uid(), 'pack': 'test_pack_2'} exec_1_db = ActionExecutionDB(action=action, runner=runner, liveaction=liveaction, status=status) exec_1_db = ActionExecution.add_or_update(exec_1_db) self.resources['exec_1'] = exec_1_db # Create some mock roles with associated permission grants # Custom role - one grant to an unrelated pack grant_db = PermissionGrantDB( resource_uid=self.resources['pack_1'].get_uid(), resource_type=ResourceType.PACK, permission_types=[PermissionType.ACTION_VIEW]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_unrelated_pack_action_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_unrelated_pack_action_grant'] = role_db # Custom role - one grant of unrelated permission type to parent action pack grant_db = PermissionGrantDB( resource_uid=self.resources['pack_2'].get_uid(), resource_type=ResourceType.PACK, permission_types=[PermissionType.RULE_VIEW]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB( name='custom_role_pack_action_grant_unrelated_permission', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles[ 'custom_role_pack_action_grant_unrelated_permission'] = role_db # Custom role - one grant of "action_view" to the parent pack of the action the execution # belongs to grant_db = PermissionGrantDB( resource_uid=self.resources['pack_2'].get_uid(), resource_type=ResourceType.PACK, permission_types=[PermissionType.ACTION_VIEW]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_pack_action_view_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_pack_action_view_grant'] = role_db # Custom role - one grant of "action_view" to the action the execution belongs to grant_db = PermissionGrantDB( resource_uid=self.resources['action_1'].get_uid(), resource_type=ResourceType.ACTION, permission_types=[PermissionType.ACTION_VIEW]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_action_view_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_action_view_grant'] = role_db # Custom role - one grant of "action_execute" to the parent pack of the action the # execution belongs to grant_db = PermissionGrantDB( resource_uid=self.resources['pack_2'].get_uid(), resource_type=ResourceType.PACK, permission_types=[PermissionType.ACTION_EXECUTE]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_pack_action_execute_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_pack_action_execute_grant'] = role_db # Custom role - one grant of "action_execute" to the the action the execution belongs to grant_db = PermissionGrantDB( resource_uid=self.resources['action_1'].get_uid(), resource_type=ResourceType.ACTION, permission_types=[PermissionType.ACTION_EXECUTE]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_db = RoleDB(name='custom_role_action_execute_grant', permission_grants=permission_grants) role_db = Role.add_or_update(role_db) self.roles['custom_role_action_execute_grant'] = role_db # Custom role - "action_all" grant on a parent action pack the execution belongs to grant_db = PermissionGrantDB( resource_uid=self.resources['pack_2'].get_uid(), resource_type=ResourceType.PACK, permission_types=[PermissionType.ACTION_ALL]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_4_db = RoleDB(name='custom_role_pack_action_all_grant', permission_grants=permission_grants) role_4_db = Role.add_or_update(role_4_db) self.roles['custom_role_pack_action_all_grant'] = role_4_db # Custom role - "action_all" grant on action the execution belongs to grant_db = PermissionGrantDB( resource_uid=self.resources['action_1'].get_uid(), resource_type=ResourceType.ACTION, permission_types=[PermissionType.ACTION_ALL]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_4_db = RoleDB(name='custom_role_action_all_grant', permission_grants=permission_grants) role_4_db = Role.add_or_update(role_4_db) self.roles['custom_role_action_all_grant'] = role_4_db # Custom role - "execution_list" grant grant_db = PermissionGrantDB( resource_uid=None, resource_type=None, permission_types=[PermissionType.EXECUTION_LIST]) grant_db = PermissionGrant.add_or_update(grant_db) permission_grants = [str(grant_db.id)] role_5_db = RoleDB(name='custom_role_execution_list_grant', permission_grants=permission_grants) role_5_db = Role.add_or_update(role_5_db) self.roles['custom_role_execution_list_grant'] = role_5_db # Create some mock role assignments user_db = self.users['custom_role_unrelated_pack_action_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_unrelated_pack_action_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users[ 'custom_role_pack_action_grant_unrelated_permission'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self. roles['custom_role_pack_action_grant_unrelated_permission'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_pack_action_view_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_pack_action_view_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_action_view_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_action_view_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_pack_action_execute_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_pack_action_execute_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_action_execute_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_action_execute_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_pack_action_all_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_pack_action_all_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_action_all_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_action_all_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db) user_db = self.users['custom_role_execution_list_grant'] role_assignment_db = UserRoleAssignmentDB( user=user_db.name, role=self.roles['custom_role_execution_list_grant'].name, source='assignments/%s.yaml' % user_db.name) UserRoleAssignment.add_or_update(role_assignment_db)
from st2common.models.db.execution import ActionExecutionDB from st2common.models.db.liveaction import LiveActionDB from st2common.models.db.notification import NotificationSchema from st2common.models.db.notification import NotificationSubSchema from st2common.models.db.runner import RunnerTypeDB from st2common.persistence.action import Action from st2common.persistence.liveaction import LiveAction from st2common.persistence.policy import Policy from st2common.models.system.common import ResourceReference from st2common.util import date as date_utils from st2common.util import isotime from st2tests.base import CleanDbTestCase ACTION_TRIGGER_TYPE = INTERNAL_TRIGGER_TYPES["action"][0] NOTIFY_TRIGGER_TYPE = INTERNAL_TRIGGER_TYPES["action"][1] MOCK_EXECUTION = ActionExecutionDB(id=bson.ObjectId(), result={"stdout": "stuff happens"}) class NotifierTestCase(CleanDbTestCase): class MockDispatcher(object): def __init__(self, tester): self.tester = tester self.notify_trigger = ResourceReference.to_string_reference( pack=NOTIFY_TRIGGER_TYPE["pack"], name=NOTIFY_TRIGGER_TYPE["name"]) self.action_trigger = ResourceReference.to_string_reference( pack=ACTION_TRIGGER_TYPE["pack"], name=ACTION_TRIGGER_TYPE["name"]) def dispatch(self, *args, **kwargs): try: