def test_liveaction_create_with_notify_on_success_only(self): created = LiveActionDB() created.action = "core.local" created.description = "" created.status = "running" created.parameters = {} notify_db = NotificationSchema() notify_sub_schema = NotificationSubSchema() notify_sub_schema.message = "Action succeeded." notify_sub_schema.data = {"foo": "bar", "bar": 1, "baz": {"k1": "v1"}} notify_db.on_success = notify_sub_schema created.notify = notify_db saved = LiveActionModelTest._save_liveaction(created) retrieved = LiveAction.get_by_id(saved.id) self.assertEqual(saved.action, retrieved.action, "Same triggertype was not returned.") # Assert notify settings saved are right. self.assertEqual(notify_sub_schema.message, retrieved.notify.on_success.message) self.assertDictEqual(notify_sub_schema.data, retrieved.notify.on_success.data) self.assertListEqual(notify_sub_schema.routes, retrieved.notify.on_success.routes) self.assertEqual(retrieved.notify.on_failure, None) self.assertEqual(retrieved.notify.on_complete, None)
def setup_action_models(cls): pack = 'wolfpack' name = 'action-1' parameters = { 'actionint': {'type': 'number', 'default': 10, 'position': 0}, 'actionfloat': {'type': 'float', 'required': False, 'position': 1}, 'actionstr': {'type': 'string', 'required': True, 'position': 2}, 'actionbool': {'type': 'boolean', 'required': False, 'position': 3}, 'actionlist': {'type': 'list', 'required': False, 'position': 4}, 'actionobject': {'type': 'object', 'required': False, 'position': 5}, 'actionnull': {'type': 'null', 'required': False, 'position': 6}, 'runnerdummy': {'type': 'string', 'default': 'actiondummy'} } action_db = ActionDB(pack=pack, name=name, description='awesomeness', enabled=True, ref=ResourceReference(name=name, pack=pack).ref, entry_point='', runner_type={'name': 'test-runner'}, parameters=parameters) ActionDBUtilsTestCase.action_db = Action.add_or_update(action_db) liveaction_db = LiveActionDB() liveaction_db.status = 'initializing' liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ActionDBUtilsTestCase.action_db.ref params = { 'actionstr': 'foo', 'some_key_that_aint_exist_in_action_or_runner': 'bar', 'runnerint': 555 } liveaction_db.parameters = params ActionDBUtilsTestCase.liveaction_db = LiveAction.add_or_update(liveaction_db)
def setup_action_models(cls): action_db = ActionDB() action_db.name = 'action-1' action_db.description = 'awesomeness' action_db.enabled = True action_db.pack = 'wolfpack' action_db.ref = ResourceReference(name=action_db.name, pack=action_db.pack).ref action_db.entry_point = '' action_db.runner_type = {'name': 'test-runner'} action_db.parameters = { 'actionstr': {'type': 'string', 'position': 1, 'required': True}, 'actionint': {'type': 'number', 'default': 10, 'position': 0}, 'runnerdummy': {'type': 'string', 'default': 'actiondummy'} } ActionDBUtilsTestCase.action_db = Action.add_or_update(action_db) liveaction_db = LiveActionDB() liveaction_db.status = 'initializing' liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ActionDBUtilsTestCase.action_db.ref params = { 'actionstr': 'foo', 'some_key_that_aint_exist_in_action_or_runner': 'bar', 'runnerint': 555 } liveaction_db.parameters = params ActionDBUtilsTestCase.liveaction_db = LiveAction.add_or_update(liveaction_db)
def test_notify_triggers_end_timestamp_none(self): liveaction_db = LiveActionDB(action='core.local') liveaction_db.id = bson.ObjectId() liveaction_db.description = '' liveaction_db.status = 'succeeded' liveaction_db.parameters = {} on_success = NotificationSubSchema(message='Action succeeded.') on_failure = NotificationSubSchema(message='Action failed.') liveaction_db.notify = NotificationSchema(on_success=on_success, on_failure=on_failure) liveaction_db.start_timestamp = date_utils.get_datetime_utc_now() # This tests for end_timestamp being set to None, which can happen when a policy cancels # a request. # The assertions within "MockDispatcher.dispatch" will validate that the underlying code # handles this properly, so all we need to do is keep the call to "notifier.process" below liveaction_db.end_timestamp = None LiveAction.add_or_update(liveaction_db) execution = MOCK_EXECUTION execution.liveaction = vars(LiveActionAPI.from_model(liveaction_db)) execution.status = liveaction_db.status dispatcher = NotifierTestCase.MockDispatcher(self) notifier = Notifier(connection=None, queues=[], trigger_dispatcher=dispatcher) notifier.process(execution)
def test_notify_triggers_jinja_patterns(self, dispatch): liveaction_db = LiveActionDB(action='core.local') liveaction_db.id = bson.ObjectId() liveaction_db.description = '' liveaction_db.status = 'succeeded' liveaction_db.parameters = {'cmd': 'mamma mia', 'runner_foo': 'foo'} on_success = NotificationSubSchema(message='Command {{action_parameters.cmd}} succeeded.', data={'stdout': '{{action_results.stdout}}'}) liveaction_db.notify = NotificationSchema(on_success=on_success) liveaction_db.start_timestamp = date_utils.get_datetime_utc_now() liveaction_db.end_timestamp = \ (liveaction_db.start_timestamp + datetime.timedelta(seconds=50)) LiveAction.add_or_update(liveaction_db) execution = MOCK_EXECUTION execution.liveaction = vars(LiveActionAPI.from_model(liveaction_db)) execution.status = liveaction_db.status notifier = Notifier(connection=None, queues=[]) notifier.process(execution) exp = {'status': 'succeeded', 'start_timestamp': isotime.format(liveaction_db.start_timestamp), 'route': 'notify.default', 'runner_ref': 'local-shell-cmd', 'channel': 'notify.default', 'message': u'Command mamma mia succeeded.', 'data': {'result': '{}', 'stdout': 'stuff happens'}, 'action_ref': u'core.local', 'execution_id': str(MOCK_EXECUTION.id), 'end_timestamp': isotime.format(liveaction_db.end_timestamp)} dispatch.assert_called_once_with('core.st2.generic.notifytrigger', payload=exp, trace_context={}) notifier.process(execution)
def _run_action(self, action_node, parent_execution_id, params, wait_for_completion=True): liveaction = LiveActionDB(action=action_node.ref) liveaction.parameters = action_param_utils.cast_params(action_ref=action_node.ref, params=params) # Setup notify for task in chain. notify = self._get_notify(action_node) if notify: liveaction.notify = notify LOG.debug('%s: Task notify set to: %s', action_node.name, liveaction.notify) liveaction.context = { 'parent': str(parent_execution_id), 'chain': vars(action_node) } liveaction, _ = action_service.request(liveaction) while (wait_for_completion and liveaction.status != LIVEACTION_STATUS_SUCCEEDED and liveaction.status != LIVEACTION_STATUS_FAILED): eventlet.sleep(1) liveaction = action_db_util.get_liveaction_by_id(liveaction.id) return liveaction
def test_notify_triggers_jinja_patterns(self, dispatch): liveaction_db = LiveActionDB(action='core.local') liveaction_db.id = bson.ObjectId() liveaction_db.description = '' liveaction_db.status = 'succeeded' liveaction_db.parameters = {'cmd': 'mamma mia', 'runner_foo': 'foo'} on_success = NotificationSubSchema(message='Command {{action_parameters.cmd}} succeeded.', data={'stdout': '{{action_results.stdout}}'}) liveaction_db.notify = NotificationSchema(on_success=on_success) liveaction_db.start_timestamp = date_utils.get_datetime_utc_now() liveaction_db.end_timestamp = \ (liveaction_db.start_timestamp + datetime.timedelta(seconds=50)) LiveAction.add_or_update(liveaction_db) execution = MOCK_EXECUTION execution.liveaction = vars(LiveActionAPI.from_model(liveaction_db)) execution.status = liveaction_db.status notifier = Notifier(connection=None, queues=[]) notifier.process(execution) exp = {'status': 'succeeded', 'start_timestamp': isotime.format(liveaction_db.start_timestamp), 'route': 'notify.default', 'runner_ref': 'local-shell-cmd', 'channel': 'notify.default', 'message': u'Command mamma mia succeeded.', 'data': {'result': '{}', 'stdout': 'stuff happens'}, 'action_ref': u'core.local', 'execution_id': str(MOCK_EXECUTION.id), 'end_timestamp': isotime.format(liveaction_db.end_timestamp)} dispatch.assert_called_once_with('core.st2.generic.notifytrigger', payload=exp, trace_context={}) notifier.process(execution)
def test_liveaction_create_with_notify_on_success_only(self): created = LiveActionDB() created.action = 'core.local' created.description = '' created.status = 'running' created.parameters = {} notify_db = NotificationSchema() notify_sub_schema = NotificationSubSchema() notify_sub_schema.message = 'Action succeeded.' notify_sub_schema.data = { 'foo': 'bar', 'bar': 1, 'baz': {'k1': 'v1'} } notify_db.on_success = notify_sub_schema created.notify = notify_db saved = LiveActionModelTest._save_liveaction(created) retrieved = LiveAction.get_by_id(saved.id) self.assertEqual(saved.action, retrieved.action, 'Same triggertype was not returned.') # Assert notify settings saved are right. self.assertEqual(notify_sub_schema.message, retrieved.notify.on_success.message) self.assertDictEqual(notify_sub_schema.data, retrieved.notify.on_success.data) self.assertListEqual(notify_sub_schema.routes, retrieved.notify.on_success.routes) self.assertEqual(retrieved.notify.on_failure, None) self.assertEqual(retrieved.notify.on_complete, None)
def post(self, execution_parameters, execution_id): """ Re-run the provided action execution optionally specifying override parameters. Handles requests: POST /executions/<id>/re_run """ parameters = execution_parameters.parameters # Note: We only really need parameters here existing_execution = self._get_one(id=execution_id, exclude_fields=self.exclude_fields) # Merge in any parameters provided by the user new_parameters = copy.deepcopy(existing_execution.parameters) new_parameters.update(parameters) # Create object for the new execution action_ref = existing_execution.action['ref'] new_execution = LiveActionDB() new_execution.action = action_ref new_execution.parameters = new_parameters result = self._handle_schedule_execution(execution=new_execution) return result
def test_notify_triggers_end_timestamp_none(self): liveaction_db = LiveActionDB(action='core.local') liveaction_db.id = bson.ObjectId() liveaction_db.description = '' liveaction_db.status = 'succeeded' liveaction_db.parameters = {} on_success = NotificationSubSchema(message='Action succeeded.') on_failure = NotificationSubSchema(message='Action failed.') liveaction_db.notify = NotificationSchema(on_success=on_success, on_failure=on_failure) liveaction_db.start_timestamp = date_utils.get_datetime_utc_now() # This tests for end_timestamp being set to None, which can happen when a policy cancels # a request. # The assertions within "MockDispatcher.dispatch" will validate that the underlying code # handles this properly, so all we need to do is keep the call to "notifier.process" below liveaction_db.end_timestamp = None LiveAction.add_or_update(liveaction_db) execution = MOCK_EXECUTION execution.liveaction = vars(LiveActionAPI.from_model(liveaction_db)) execution.status = liveaction_db.status dispatcher = NotifierTestCase.MockDispatcher(self) notifier = Notifier(connection=None, queues=[], trigger_dispatcher=dispatcher) notifier.process(execution)
def test_liveaction_create_with_notify_on_success_only(self): created = LiveActionDB() created.action = 'core.local' created.description = '' created.status = 'running' created.parameters = {} notify_db = NotificationSchema() notify_sub_schema = NotificationSubSchema() notify_sub_schema.message = 'Action succeeded.' notify_sub_schema.data = {'foo': 'bar', 'bar': 1, 'baz': {'k1': 'v1'}} notify_db.on_success = notify_sub_schema created.notify = notify_db saved = LiveActionModelTest._save_liveaction(created) retrieved = LiveAction.get_by_id(saved.id) self.assertEqual(saved.action, retrieved.action, 'Same triggertype was not returned.') # Assert notify settings saved are right. self.assertEqual(notify_sub_schema.message, retrieved.notify.on_success.message) self.assertDictEqual(notify_sub_schema.data, retrieved.notify.on_success.data) self.assertListEqual(notify_sub_schema.routes, retrieved.notify.on_success.routes) self.assertEqual(retrieved.notify.on_failure, None) self.assertEqual(retrieved.notify.on_complete, None)
def test_update_same_liveaction_status(self): liveaction_db = LiveActionDB() liveaction_db.status = 'requested' liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ResourceReference( name=ActionDBUtilsTestCase.action_db.name, pack=ActionDBUtilsTestCase.action_db.pack).ref params = { 'actionstr': 'foo', 'some_key_that_aint_exist_in_action_or_runner': 'bar', 'runnerint': 555 } liveaction_db.parameters = params liveaction_db = LiveAction.add_or_update(liveaction_db) origliveaction_db = copy.copy(liveaction_db) # Update by id. newliveaction_db = action_db_utils.update_liveaction_status( status='requested', liveaction_id=liveaction_db.id) # Verify id didn't change. self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, 'requested') # Verify that state is not published. self.assertFalse(LiveActionPublisher.publish_state.called)
def test_update_LiveAction_status_invalid(self): liveaction_db = LiveActionDB() liveaction_db.status = "initializing" liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ResourceReference( name=ActionDBUtilsTestCase.action_db.name, pack=ActionDBUtilsTestCase.action_db.pack, ).ref params = { "actionstr": "foo", "some_key_that_aint_exist_in_action_or_runner": "bar", "runnerint": 555, } liveaction_db.parameters = params liveaction_db = LiveAction.add_or_update(liveaction_db) # Update by id. self.assertRaises( ValueError, action_db_utils.update_liveaction_status, status="mea culpa", liveaction_id=liveaction_db.id, ) # Verify that state is not published. self.assertFalse(LiveActionPublisher.publish_state.called)
def post(self, execution_parameters, execution_id): """ Re-run the provided action execution optionally specifying override parameters. Handles requests: POST /executions/<id>/re_run """ parameters = execution_parameters.parameters # Note: We only really need parameters here existing_execution = self._get_one(id=execution_id, exclude_fields=self.exclude_fields) # Merge in any parameters provided by the user new_parameters = copy.deepcopy(existing_execution.parameters) new_parameters.update(parameters) # Create object for the new execution action_ref = existing_execution.action['ref'] new_execution = LiveActionDB() new_execution.action = action_ref new_execution.parameters = new_parameters result = self._handle_schedule_execution(execution=new_execution) return result
def test_update_liveaction_with_incorrect_output_schema(self): liveaction_db = LiveActionDB() liveaction_db.status = 'initializing' liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ResourceReference( name=ActionDBUtilsTestCase.action_db.name, pack=ActionDBUtilsTestCase.action_db.pack).ref params = { 'actionstr': 'foo', 'some_key_that_aint_exist_in_action_or_runner': 'bar', 'runnerint': 555 } liveaction_db.parameters = params runner = mock.MagicMock() runner.output_schema = {"notaparam": {"type": "boolean"}} liveaction_db.runner = runner liveaction_db = LiveAction.add_or_update(liveaction_db) origliveaction_db = copy.copy(liveaction_db) now = get_datetime_utc_now() status = 'succeeded' result = 'Work is done.' context = {'third_party_id': uuid.uuid4().hex} newliveaction_db = action_db_utils.update_liveaction_status( status=status, result=result, context=context, end_timestamp=now, liveaction_id=liveaction_db.id) self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, status) self.assertEqual(newliveaction_db.result, result) self.assertDictEqual(newliveaction_db.context, context) self.assertEqual(newliveaction_db.end_timestamp, now)
def _run_action(self, action_node, parent_execution_id, params, wait_for_completion=True): liveaction = LiveActionDB(action=action_node.ref) liveaction.parameters = action_param_utils.cast_params( action_ref=action_node.ref, params=params) # Setup notify for task in chain. notify = self._get_notify(action_node) if notify: liveaction.notify = notify LOG.debug('%s: Task notify set to: %s', action_node.name, liveaction.notify) liveaction.context = { 'parent': str(parent_execution_id), 'chain': vars(action_node) } liveaction, _ = action_service.request(liveaction) while (wait_for_completion and liveaction.status != LIVEACTION_STATUS_SUCCEEDED and liveaction.status != LIVEACTION_STATUS_FAILED): eventlet.sleep(1) liveaction = action_db_util.get_liveaction_by_id(liveaction.id) return liveaction
def test_update_canceled_liveaction(self): liveaction_db = LiveActionDB() liveaction_db.status = "initializing" liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ResourceReference( name=ActionDBUtilsTestCase.action_db.name, pack=ActionDBUtilsTestCase.action_db.pack, ).ref params = { "actionstr": "foo", "some_key_that_aint_exist_in_action_or_runner": "bar", "runnerint": 555, } liveaction_db.parameters = params liveaction_db = LiveAction.add_or_update(liveaction_db) origliveaction_db = copy.copy(liveaction_db) # Update by id. newliveaction_db = action_db_utils.update_liveaction_status( status="running", liveaction_id=liveaction_db.id) # Verify id didn't change. self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, "running") # Verify that state is published. self.assertTrue(LiveActionPublisher.publish_state.called) LiveActionPublisher.publish_state.assert_called_once_with( newliveaction_db, "running") # Cancel liveaction. now = get_datetime_utc_now() status = "canceled" newliveaction_db = action_db_utils.update_liveaction_status( status=status, end_timestamp=now, liveaction_id=liveaction_db.id) self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, status) self.assertEqual(newliveaction_db.end_timestamp, now) # Since liveaction has already been canceled, check that anymore update of # status, result, context, and end timestamp are not processed. now = get_datetime_utc_now() status = "succeeded" result = "Work is done." context = {"third_party_id": uuid.uuid4().hex} newliveaction_db = action_db_utils.update_liveaction_status( status=status, result=result, context=context, end_timestamp=now, liveaction_id=liveaction_db.id, ) self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, "canceled") self.assertNotEqual(newliveaction_db.result, result) self.assertNotEqual(newliveaction_db.context, context) self.assertNotEqual(newliveaction_db.end_timestamp, now)
def _get_execution_db_model( self, status=action_constants.LIVEACTION_STATUS_REQUESTED): live_action_db = LiveActionDB() live_action_db.status = status live_action_db.start_timestamp = date_utils.get_datetime_utc_now() live_action_db.action = ResourceReference(name='test_action', pack='test_pack').ref live_action_db.parameters = None return action.LiveAction.add_or_update(live_action_db, publish=False)
def _get_action_exec_db_model(self, params): liveaction_db = LiveActionDB() liveaction_db.status = 'initializing' liveaction_db.start_timestamp = date_utils.get_datetime_utc_now() liveaction_db.action = ResourceReference(name=ParamsUtilsTest.action_db.name, pack=ParamsUtilsTest.action_db.pack).ref liveaction_db.parameters = params return liveaction_db
def _get_action_exec_db_model(self, action_db, params): liveaction_db = LiveActionDB() liveaction_db.status = action_constants.LIVEACTION_STATUS_REQUESTED liveaction_db.start_timestamp = date_utils.get_datetime_utc_now() liveaction_db.action = ResourceReference(name=action_db.name, pack=action_db.pack).ref liveaction_db.parameters = params liveaction_db.context = {'user': cfg.CONF.system_user.user} return liveaction_db
def _get_execution_db_model(self, status=action_constants.LIVEACTION_STATUS_REQUESTED): live_action_db = LiveActionDB() live_action_db.status = status live_action_db.start_timestamp = date_utils.get_datetime_utc_now() live_action_db.action = ResourceReference( name='test_action', pack='test_pack').ref live_action_db.parameters = None return action.LiveAction.add_or_update(live_action_db, publish=False)
def _get_action_exec_db_model(self, params): liveaction_db = LiveActionDB() liveaction_db.status = 'initializing' liveaction_db.start_timestamp = datetime.datetime.utcnow() liveaction_db.action = ResourceReference(name=ParamsUtilsTest.action_db.name, pack=ParamsUtilsTest.action_db.pack).ref liveaction_db.parameters = params return liveaction_db
def _get_action_exec_db_model(self, action_db, params): liveaction_db = LiveActionDB() liveaction_db.status = action_constants.LIVEACTION_STATUS_REQUESTED liveaction_db.start_timestamp = date_utils.get_datetime_utc_now() liveaction_db.action = ResourceReference( name=action_db.name, pack=action_db.pack).ref liveaction_db.parameters = params liveaction_db.context = {'user': cfg.CONF.system_user.user} return liveaction_db
def _get_failingaction_exec_db_model(self, params): liveaction_db = LiveActionDB() liveaction_db.status = action_constants.LIVEACTION_STATUS_REQUESTED liveaction_db.start_timestamp = datetime.datetime.now() liveaction_db.action = ResourceReference( name=RunnerContainerTest.failingaction_db.name, pack=RunnerContainerTest.failingaction_db.pack).ref liveaction_db.parameters = params liveaction_db.context = {'user': cfg.CONF.system_user.user} return liveaction_db
def _invoke_action(self, action_db, runnertype_db, params, context=None, additional_contexts=None): """ Schedule an action execution. :type action_exec_spec: :class:`ActionExecutionSpecDB` :param params: Partially rendered parameters to execute the action with. :type params: ``dict`` :rtype: :class:`LiveActionDB` on successful scheduling, None otherwise. """ action_ref = action_db.ref runnertype_db = action_utils.get_runnertype_by_name( action_db.runner_type['name']) liveaction_db = LiveActionDB(action=action_ref, context=context, parameters=params) try: liveaction_db.parameters = self.get_resolved_parameters( runnertype_db=runnertype_db, action_db=action_db, params=liveaction_db.parameters, context=liveaction_db.context, additional_contexts=additional_contexts) except param_exc.ParamException as e: # We still need to create a request, so liveaction_db is assigned an ID liveaction_db, execution_db = action_service.create_request( liveaction_db) # By this point the execution is already in the DB therefore need to mark it failed. _, e, tb = sys.exc_info() action_service.update_status( liveaction=liveaction_db, new_status=action_constants.LIVEACTION_STATUS_FAILED, result={ 'error': str(e), 'traceback': ''.join(traceback.format_tb(tb, 20)) }) # Might be a good idea to return the actual ActionExecution rather than bubble up # the exception. raise validation_exc.ValueValidationException(str(e)) liveaction_db, execution_db = action_service.request(liveaction_db) return execution_db
def test_update_canceled_liveaction(self): liveaction_db = LiveActionDB() liveaction_db.status = 'initializing' liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ResourceReference( name=ActionDBUtilsTestCase.action_db.name, pack=ActionDBUtilsTestCase.action_db.pack).ref params = { 'actionstr': 'foo', 'some_key_that_aint_exist_in_action_or_runner': 'bar', 'runnerint': 555 } liveaction_db.parameters = params liveaction_db = LiveAction.add_or_update(liveaction_db) origliveaction_db = copy.copy(liveaction_db) # Update by id. newliveaction_db = action_db_utils.update_liveaction_status( status='running', liveaction_id=liveaction_db.id) # Verify id didn't change. self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, 'running') # Verify that state is published. self.assertTrue(LiveActionPublisher.publish_state.called) LiveActionPublisher.publish_state.assert_called_once_with(newliveaction_db, 'running') # Cancel liveaction. now = get_datetime_utc_now() status = 'canceled' newliveaction_db = action_db_utils.update_liveaction_status( status=status, end_timestamp=now, liveaction_id=liveaction_db.id) self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, status) self.assertEqual(newliveaction_db.end_timestamp, now) # Since liveaction has already been canceled, check that anymore update of # status, result, context, and end timestamp are not processed. now = get_datetime_utc_now() status = 'succeeded' result = 'Work is done.' context = {'third_party_id': uuid.uuid4().hex} newliveaction_db = action_db_utils.update_liveaction_status( status=status, result=result, context=context, end_timestamp=now, liveaction_id=liveaction_db.id) self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, 'canceled') self.assertNotEqual(newliveaction_db.result, result) self.assertNotEqual(newliveaction_db.context, context) self.assertNotEqual(newliveaction_db.end_timestamp, now)
def test_notify_triggers(self): liveaction = LiveActionDB(action='core.local') liveaction.description = '' liveaction.status = 'succeeded' liveaction.parameters = {} on_success = NotificationSubSchema(message='Action succeeded.') on_failure = NotificationSubSchema(message='Action failed.') liveaction.notify = NotificationSchema(on_success=on_success, on_failure=on_failure) liveaction.start_timestamp = date_utils.get_datetime_utc_now() dispatcher = NotifierTestCase.MockDispatcher(self) notifier = Notifier(connection=None, queues=[], trigger_dispatcher=dispatcher) notifier.process(liveaction)
def test_notify_triggers(self): liveaction = LiveActionDB(action='core.local') liveaction.description = '' liveaction.status = 'succeeded' liveaction.parameters = {} on_success = NotificationSubSchema(message='Action succeeded.') on_failure = NotificationSubSchema(message='Action failed.') liveaction.notify = NotificationSchema(on_success=on_success, on_failure=on_failure) liveaction.start_timestamp = date_utils.get_datetime_utc_now() dispatcher = NotifierTestCase.MockDispatcher(self) notifier = Notifier(connection=None, queues=[], trigger_dispatcher=dispatcher) notifier.process(liveaction)
def test_update_liveaction_result_with_dotted_key(self): liveaction_db = LiveActionDB() liveaction_db.status = "initializing" liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ResourceReference( name=ActionDBUtilsTestCase.action_db.name, pack=ActionDBUtilsTestCase.action_db.pack, ).ref params = { "actionstr": "foo", "some_key_that_aint_exist_in_action_or_runner": "bar", "runnerint": 555, } liveaction_db.parameters = params liveaction_db = LiveAction.add_or_update(liveaction_db) origliveaction_db = copy.copy(liveaction_db) # Update by id. newliveaction_db = action_db_utils.update_liveaction_status( status="running", liveaction_id=liveaction_db.id) # Verify id didn't change. self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, "running") # Verify that state is published. self.assertTrue(LiveActionPublisher.publish_state.called) LiveActionPublisher.publish_state.assert_called_once_with( newliveaction_db, "running") now = get_datetime_utc_now() status = "succeeded" result = {"a": 1, "b": True, "a.b.c": "abc"} context = {"third_party_id": uuid.uuid4().hex} newliveaction_db = action_db_utils.update_liveaction_status( status=status, result=result, context=context, end_timestamp=now, liveaction_id=liveaction_db.id, ) self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, status) self.assertIn("a.b.c", list(result.keys())) self.assertDictEqual(newliveaction_db.result, result) self.assertDictEqual(newliveaction_db.context, context) self.assertEqual(newliveaction_db.end_timestamp, now)
def _build_liveaction_object(self, action_node, resolved_params, parent_context): liveaction = LiveActionDB(action=action_node.ref) # Setup notify for task in chain. notify = self._get_notify(action_node) if notify: liveaction.notify = notify LOG.debug('%s: Task notify set to: %s', action_node.name, liveaction.notify) liveaction.context = { 'parent': parent_context, 'chain': vars(action_node) } liveaction.parameters = action_param_utils.cast_params(action_ref=action_node.ref, params=resolved_params) return liveaction
def _build_liveaction_object(self, action_node, resolved_params, parent_context): liveaction = LiveActionDB(action=action_node.ref) # Setup notify for task in chain. notify = self._get_notify(action_node) if notify: liveaction.notify = notify LOG.debug('%s: Task notify set to: %s', action_node.name, liveaction.notify) liveaction.context = { 'parent': parent_context, 'chain': vars(action_node) } liveaction.parameters = action_param_utils.cast_params(action_ref=action_node.ref, params=resolved_params) return liveaction
def test_update_liveaction_result_with_dotted_key(self): liveaction_db = LiveActionDB() liveaction_db.status = 'initializing' liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ResourceReference( name=ActionDBUtilsTestCase.action_db.name, pack=ActionDBUtilsTestCase.action_db.pack).ref params = { 'actionstr': 'foo', 'some_key_that_aint_exist_in_action_or_runner': 'bar', 'runnerint': 555 } liveaction_db.parameters = params liveaction_db = LiveAction.add_or_update(liveaction_db) origliveaction_db = copy.copy(liveaction_db) # Update by id. newliveaction_db = action_db_utils.update_liveaction_status( status='running', liveaction_id=liveaction_db.id) # Verify id didn't change. self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, 'running') # Verify that state is published. self.assertTrue(LiveActionPublisher.publish_state.called) LiveActionPublisher.publish_state.assert_called_once_with( newliveaction_db, 'running') now = get_datetime_utc_now() status = 'succeeded' result = {'a': 1, 'b': True, 'a.b.c': 'abc'} context = {'third_party_id': uuid.uuid4().hex} newliveaction_db = action_db_utils.update_liveaction_status( status=status, result=result, context=context, end_timestamp=now, liveaction_id=liveaction_db.id) self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, status) self.assertIn('a.b.c', result.keys()) self.assertDictEqual(newliveaction_db.result, result) self.assertDictEqual(newliveaction_db.context, context) self.assertEqual(newliveaction_db.end_timestamp, now)
def test_liveaction_create_with_notify_both_on_success_and_on_error(self): created = LiveActionDB() created.action = 'core.local' created.description = '' created.status = 'running' created.parameters = {} on_success = NotificationSubSchema(message='Action succeeded.') on_failure = NotificationSubSchema(message='Action failed.') created.notify = NotificationSchema(on_success=on_success, on_failure=on_failure) saved = LiveActionModelTest._save_liveaction(created) retrieved = LiveAction.get_by_id(saved.id) self.assertEqual(saved.action, retrieved.action, 'Same triggertype was not returned.') # Assert notify settings saved are right. self.assertEqual(on_success.message, retrieved.notify.on_success.message) self.assertEqual(on_failure.message, retrieved.notify.on_failure.message) self.assertEqual(retrieved.notify.on_complete, None)
def test_liveaction_create_with_notify_both_on_success_and_on_error(self): created = LiveActionDB() created.action = 'core.local' created.description = '' created.status = 'running' created.parameters = {} on_success = NotificationSubSchema(message='Action succeeded.') on_failure = NotificationSubSchema(message='Action failed.') created.notify = NotificationSchema(on_success=on_success, on_failure=on_failure) saved = LiveActionModelTest._save_liveaction(created) retrieved = LiveAction.get_by_id(saved.id) self.assertEqual(saved.action, retrieved.action, 'Same triggertype was not returned.') # Assert notify settings saved are right. self.assertEqual(on_success.message, retrieved.notify.on_success.message) self.assertEqual(on_failure.message, retrieved.notify.on_failure.message) self.assertEqual(retrieved.notify.on_complete, None)
def _invoke_action(self, action_db, runnertype_db, params, context=None, additional_contexts=None): """ Schedule an action execution. :type action_exec_spec: :class:`ActionExecutionSpecDB` :param params: Partially rendered parameters to execute the action with. :type params: ``dict`` :rtype: :class:`LiveActionDB` on successful scheduling, None otherwise. """ action_ref = action_db.ref runnertype_db = action_utils.get_runnertype_by_name(action_db.runner_type['name']) liveaction_db = LiveActionDB(action=action_ref, context=context, parameters=params) try: liveaction_db.parameters = self.get_resolved_parameters( runnertype_db=runnertype_db, action_db=action_db, params=liveaction_db.parameters, context=liveaction_db.context, additional_contexts=additional_contexts) except param_exc.ParamException as e: # We still need to create a request, so liveaction_db is assigned an ID liveaction_db, execution_db = action_service.create_request(liveaction_db) # By this point the execution is already in the DB therefore need to mark it failed. _, e, tb = sys.exc_info() action_service.update_status( liveaction=liveaction_db, new_status=action_constants.LIVEACTION_STATUS_FAILED, result={'error': six.text_type(e), 'traceback': ''.join(traceback.format_tb(tb, 20))}) # Might be a good idea to return the actual ActionExecution rather than bubble up # the exception. raise validation_exc.ValueValidationException(six.text_type(e)) liveaction_db, execution_db = action_service.request(liveaction_db) return execution_db
def test_notify_triggers_jinja_patterns(self, dispatch): liveaction_db = LiveActionDB(action="core.local") liveaction_db.id = bson.ObjectId() liveaction_db.description = "" liveaction_db.status = "succeeded" liveaction_db.parameters = {"cmd": "mamma mia", "runner_foo": "foo"} on_success = NotificationSubSchema( message="Command {{action_parameters.cmd}} succeeded.", data={"stdout": "{{action_results.stdout}}"}, ) liveaction_db.notify = NotificationSchema(on_success=on_success) liveaction_db.start_timestamp = date_utils.get_datetime_utc_now() liveaction_db.end_timestamp = (liveaction_db.start_timestamp + datetime.timedelta(seconds=50)) LiveAction.add_or_update(liveaction_db) execution = MOCK_EXECUTION execution.liveaction = vars(LiveActionAPI.from_model(liveaction_db)) execution.status = liveaction_db.status notifier = Notifier(connection=None, queues=[]) notifier.process(execution) exp = { "status": "succeeded", "start_timestamp": isotime.format(liveaction_db.start_timestamp), "route": "notify.default", "runner_ref": "local-shell-cmd", "channel": "notify.default", "message": "Command mamma mia succeeded.", "data": { "result": "{}", "stdout": "stuff happens" }, "action_ref": "core.local", "execution_id": str(MOCK_EXECUTION.id), "end_timestamp": isotime.format(liveaction_db.end_timestamp), } dispatch.assert_called_once_with("core.st2.generic.notifytrigger", payload=exp, trace_context={}) notifier.process(execution)
def test_update_liveaction_result_with_dotted_key(self): liveaction_db = LiveActionDB() liveaction_db.status = 'initializing' liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ResourceReference( name=ActionDBUtilsTestCase.action_db.name, pack=ActionDBUtilsTestCase.action_db.pack).ref params = { 'actionstr': 'foo', 'some_key_that_aint_exist_in_action_or_runner': 'bar', 'runnerint': 555 } liveaction_db.parameters = params liveaction_db = LiveAction.add_or_update(liveaction_db) origliveaction_db = copy.copy(liveaction_db) # Update by id. newliveaction_db = action_db_utils.update_liveaction_status( status='running', liveaction_id=liveaction_db.id) # Verify id didn't change. self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, 'running') # Verify that state is published. self.assertTrue(LiveActionPublisher.publish_state.called) LiveActionPublisher.publish_state.assert_called_once_with(newliveaction_db, 'running') now = get_datetime_utc_now() status = 'succeeded' result = {'a': 1, 'b': True, 'a.b.c': 'abc'} context = {'third_party_id': uuid.uuid4().hex} newliveaction_db = action_db_utils.update_liveaction_status( status=status, result=result, context=context, end_timestamp=now, liveaction_id=liveaction_db.id) self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, status) self.assertIn('a.b.c', list(result.keys())) self.assertDictEqual(newliveaction_db.result, result) self.assertDictEqual(newliveaction_db.context, context) self.assertEqual(newliveaction_db.end_timestamp, now)
def test_update_LiveAction_status_invalid(self): liveaction_db = LiveActionDB() liveaction_db.status = 'initializing' liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ResourceReference( name=ActionDBUtilsTestCase.action_db.name, pack=ActionDBUtilsTestCase.action_db.pack).ref params = { 'actionstr': 'foo', 'some_key_that_aint_exist_in_action_or_runner': 'bar', 'runnerint': 555 } liveaction_db.parameters = params liveaction_db = LiveAction.add_or_update(liveaction_db) # Update by id. self.assertRaises(ValueError, action_db_utils.update_liveaction_status, status='mea culpa', liveaction_id=liveaction_db.id) # Verify that state is not published. self.assertFalse(LiveActionPublisher.publish_state.called)
def test_notify_triggers(self): liveaction_db = LiveActionDB(action='core.local') liveaction_db.id = bson.ObjectId() liveaction_db.description = '' liveaction_db.status = 'succeeded' liveaction_db.parameters = {} on_success = NotificationSubSchema(message='Action succeeded.') on_failure = NotificationSubSchema(message='Action failed.') liveaction_db.notify = NotificationSchema(on_success=on_success, on_failure=on_failure) liveaction_db.start_timestamp = date_utils.get_datetime_utc_now() liveaction_db.end_timestamp = \ (liveaction_db.start_timestamp + datetime.timedelta(seconds=50)) LiveAction.add_or_update(liveaction_db) execution = MOCK_EXECUTION execution.liveaction = vars(LiveActionAPI.from_model(liveaction_db)) execution.status = liveaction_db.status dispatcher = NotifierTestCase.MockDispatcher(self) notifier = Notifier(connection=None, queues=[], trigger_dispatcher=dispatcher) notifier.process(execution)
def test_notify_triggers(self): liveaction_db = LiveActionDB(action='core.local') liveaction_db.id = bson.ObjectId() liveaction_db.description = '' liveaction_db.status = 'succeeded' liveaction_db.parameters = {} on_success = NotificationSubSchema(message='Action succeeded.') on_failure = NotificationSubSchema(message='Action failed.') liveaction_db.notify = NotificationSchema(on_success=on_success, on_failure=on_failure) liveaction_db.start_timestamp = date_utils.get_datetime_utc_now() liveaction_db.end_timestamp = \ (liveaction_db.start_timestamp + datetime.timedelta(seconds=50)) LiveAction.add_or_update(liveaction_db) execution = MOCK_EXECUTION execution.liveaction = vars(LiveActionAPI.from_model(liveaction_db)) execution.status = liveaction_db.status dispatcher = NotifierTestCase.MockDispatcher(self) notifier = Notifier(connection=None, queues=[], trigger_dispatcher=dispatcher) notifier.process(execution)
def test_liveaction_crud_no_notify(self): created = LiveActionDB() created.action = "core.local" created.description = "" created.status = "running" created.parameters = {} saved = LiveActionModelTest._save_liveaction(created) retrieved = LiveAction.get_by_id(saved.id) self.assertEqual(saved.action, retrieved.action, "Same triggertype was not returned.") self.assertEqual(retrieved.notify, None) # Test update self.assertIsNone(retrieved.end_timestamp) retrieved.end_timestamp = date_utils.get_datetime_utc_now() updated = LiveAction.add_or_update(retrieved) self.assertTrue(updated.end_timestamp == retrieved.end_timestamp) # Test delete LiveActionModelTest._delete([retrieved]) try: retrieved = LiveAction.get_by_id(saved.id) except StackStormDBObjectNotFoundError: retrieved = None self.assertIsNone(retrieved, "managed to retrieve after failure.")
def test_liveaction_crud_no_notify(self): created = LiveActionDB() created.action = 'core.local' created.description = '' created.status = 'running' created.parameters = {} saved = LiveActionModelTest._save_liveaction(created) retrieved = LiveAction.get_by_id(saved.id) self.assertEqual(saved.action, retrieved.action, 'Same triggertype was not returned.') self.assertEqual(retrieved.notify, None) # Test update self.assertTrue(retrieved.end_timestamp is None) retrieved.end_timestamp = date_utils.get_datetime_utc_now() updated = LiveAction.add_or_update(retrieved) self.assertTrue(updated.end_timestamp == retrieved.end_timestamp) # Test delete LiveActionModelTest._delete([retrieved]) try: retrieved = LiveAction.get_by_id(saved.id) except StackStormDBObjectNotFoundError: retrieved = None self.assertIsNone(retrieved, 'managed to retrieve after failure.')
def test_liveaction_crud_no_notify(self): created = LiveActionDB() created.action = 'core.local' created.description = '' created.status = 'running' created.parameters = {} saved = LiveActionModelTest._save_liveaction(created) retrieved = LiveAction.get_by_id(saved.id) self.assertEqual(saved.action, retrieved.action, 'Same triggertype was not returned.') self.assertEqual(retrieved.notify, None) # Test update self.assertTrue(retrieved.end_timestamp is None) retrieved.end_timestamp = date_utils.get_datetime_utc_now() updated = LiveAction.add_or_update(retrieved) self.assertTrue(updated.end_timestamp == retrieved.end_timestamp) # Test delete LiveActionModelTest._delete([retrieved]) try: retrieved = LiveAction.get_by_id(saved.id) except ValueError: retrieved = None self.assertIsNone(retrieved, 'managed to retrieve after failure.')
def test_update_liveaction_with_incorrect_output_schema(self): liveaction_db = LiveActionDB() liveaction_db.status = 'initializing' liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ResourceReference( name=ActionDBUtilsTestCase.action_db.name, pack=ActionDBUtilsTestCase.action_db.pack).ref params = { 'actionstr': 'foo', 'some_key_that_aint_exist_in_action_or_runner': 'bar', 'runnerint': 555 } liveaction_db.parameters = params runner = mock.MagicMock() runner.output_schema = { "notaparam": { "type": "boolean" } } liveaction_db.runner = runner liveaction_db = LiveAction.add_or_update(liveaction_db) origliveaction_db = copy.copy(liveaction_db) now = get_datetime_utc_now() status = 'succeeded' result = 'Work is done.' context = {'third_party_id': uuid.uuid4().hex} newliveaction_db = action_db_utils.update_liveaction_status( status=status, result=result, context=context, end_timestamp=now, liveaction_id=liveaction_db.id) self.assertEqual(origliveaction_db.id, newliveaction_db.id) self.assertEqual(newliveaction_db.status, status) self.assertEqual(newliveaction_db.result, result) self.assertDictEqual(newliveaction_db.context, context) self.assertEqual(newliveaction_db.end_timestamp, now)
def setup_action_models(cls): pack = "wolfpack" name = "action-1" parameters = { "actionint": { "type": "number", "default": 10, "position": 0 }, "actionfloat": { "type": "float", "required": False, "position": 1 }, "actionstr": { "type": "string", "required": True, "position": 2 }, "actionbool": { "type": "boolean", "required": False, "position": 3 }, "actionarray": { "type": "array", "required": False, "position": 4 }, "actionlist": { "type": "list", "required": False, "position": 5 }, "actionobject": { "type": "object", "required": False, "position": 6 }, "actionnull": { "type": "null", "required": False, "position": 7 }, "runnerdummy": { "type": "string", "default": "actiondummy" }, } action_db = ActionDB( pack=pack, name=name, description="awesomeness", enabled=True, ref=ResourceReference(name=name, pack=pack).ref, entry_point="", runner_type={"name": "test-runner"}, parameters=parameters, ) ActionDBUtilsTestCase.action_db = Action.add_or_update(action_db) liveaction_db = LiveActionDB() liveaction_db.status = "initializing" liveaction_db.start_timestamp = get_datetime_utc_now() liveaction_db.action = ActionDBUtilsTestCase.action_db.ref params = { "actionstr": "foo", "some_key_that_aint_exist_in_action_or_runner": "bar", "runnerint": 555, } liveaction_db.parameters = params ActionDBUtilsTestCase.liveaction_db = LiveAction.add_or_update( liveaction_db)