def test_get_finalized_params_system_values(self): KeyValuePair.add_or_update(KeyValuePairDB(name='actionstr', value='foo')) KeyValuePair.add_or_update(KeyValuePairDB(name='actionnumber', value='1.0')) params = { 'runnerint': 555 } liveaction_db = self._get_liveaction_model(params) runner_params, action_params = param_utils.get_finalized_params( ParamsUtilsTest.runnertype_db.runner_parameters, ParamsUtilsTest.action_system_default_db.parameters, liveaction_db.parameters, liveaction_db.context) # Asserts for runner params. # Assert that default values for runner params are resolved. self.assertEqual(runner_params.get('runnerstr'), 'defaultfoo') # Assert that a runner param from action exec is picked up. self.assertEqual(runner_params.get('runnerint'), 555) # Assert that an immutable param cannot be overridden by action param or execution param. self.assertEqual(runner_params.get('runnerimmutable'), 'runnerimmutable') # Asserts for action params. self.assertEqual(action_params.get('actionstr'), 'foo') self.assertEqual(action_params.get('actionnumber'), 1.0)
def test_get_finalized_params(self): params = { 'actionstr': 'foo', 'some_key_that_aint_exist_in_action_or_runner': 'bar', 'runnerint': 555, 'runnerimmutable': 'failed_override', 'actionimmutable': 'failed_override' } liveaction_db = self._get_action_exec_db_model(params) runner_params, action_params = param_utils.get_finalized_params( ParamsUtilsTest.runnertype_db.runner_parameters, ParamsUtilsTest.action_db.parameters, liveaction_db.parameters) # Asserts for runner params. # Assert that default values for runner params are resolved. self.assertEqual(runner_params.get('runnerstr'), 'defaultfoo') # Assert that a runner param from action exec is picked up. self.assertEqual(runner_params.get('runnerint'), 555) # Assert that a runner param can be overriden by action param default. self.assertEqual(runner_params.get('runnerdummy'), 'actiondummy') # Assert that an immutable param cannot be overriden by action param or execution param. self.assertEqual(runner_params.get('runnerimmutable'), 'runnerimmutable') # Asserts for action params. self.assertEqual(action_params.get('actionstr'), 'foo') # Assert that a param that is provided in action exec that isn't in action or runner params # isn't in resolved params. self.assertEqual(action_params.get('some_key_that_aint_exist_in_action_or_runner'), None) # Assert that an immutable param cannot be overriden by execution param. self.assertEqual(action_params.get('actionimmutable'), 'actionimmutable') # Assert that none of runner params are present in action_params. for k in action_params: self.assertTrue(k not in runner_params, 'Param ' + k + ' is a runner param.')
def _do_run(self, runner, runnertype_db, action_db, actionexec_db): # Finalized parameters are resolved and then rendered. runner_params, action_params = param_utils.get_finalized_params( runnertype_db.runner_parameters, action_db.parameters, actionexec_db.parameters) resolved_entry_point = self._get_entry_point_abs_path( action_db.pack, action_db.entry_point) runner.container_service = RunnerContainerService() runner.action = action_db runner.action_name = action_db.name runner.action_execution_id = str(actionexec_db.id) runner.entry_point = resolved_entry_point runner.runner_parameters = runner_params runner.context = getattr(actionexec_db, 'context', dict()) runner.callback = getattr(actionexec_db, 'callback', dict()) runner.libs_dir_path = self._get_action_libs_abs_path( action_db.pack, action_db.entry_point) runner.auth_token = self._create_auth_token(runner.context) try: LOG.debug('Performing pre-run for runner: %s', runner) runner.pre_run() LOG.debug('Performing run for runner: %s', runner) run_result = runner.run(action_params) LOG.debug('Result of run: %s', run_result) except: LOG.exception('Failed to run action.') _, ex, tb = sys.exc_info() # mark execution as failed. runner.container_service.report_status(ACTIONEXEC_STATUS_FAILED) # include the error message and traceback to try and provide some hints. runner.container_service.report_result({ 'message': str(ex), 'traceback': ''.join(traceback.format_tb(tb, 20)) }) finally: # Always clean-up the auth_token try: self._delete_auth_token(runner.auth_token) except: LOG.warn('Unable to clean-up auth_token.') # Re-load Action Execution from DB: actionexec_db = get_actionexec_by_id(actionexec_db.id) # TODO: Store payload when DB model can hold payload data action_result = runner.container_service.get_result() actionexec_status = runner.container_service.get_status() LOG.debug('Result as reporter to container service: %s', action_result) if action_result is None: # If the runner didn't set an exit code then the action didn't complete. # Therefore, the action produced an error. result = False if not actionexec_status: actionexec_status = ACTIONEXEC_STATUS_FAILED runner.container_service.report_status(actionexec_status) else: # So long as the runner produced an exit code, we can assume that the # Live Action ran to completion. result = True actionexec_db.result = action_result if not actionexec_status: actionexec_status = ACTIONEXEC_STATUS_SUCCEEDED runner.container_service.report_status(actionexec_status) # Push result data and updated status to ActionExecution DB actionexec_db = update_actionexecution_status( actionexec_status, actionexec_db=actionexec_db) LOG.debug('Performing post_run for runner: %s', runner) runner.post_run() runner.container_service = None return result, actionexec_db
def _do_run(self, runner, runnertype_db, action_db, liveaction_db): # Finalized parameters are resolved and then rendered. runner_params, action_params = param_utils.get_finalized_params( runnertype_db.runner_parameters, action_db.parameters, liveaction_db.parameters) resolved_entry_point = self._get_entry_point_abs_path( action_db.pack, action_db.entry_point) runner.container_service = RunnerContainerService() runner.action = action_db runner.action_name = action_db.name runner.liveaction_id = str(liveaction_db.id) runner.entry_point = resolved_entry_point runner.runner_parameters = runner_params runner.context = getattr(liveaction_db, 'context', dict()) runner.callback = getattr(liveaction_db, 'callback', dict()) runner.libs_dir_path = self._get_action_libs_abs_path( action_db.pack, action_db.entry_point) runner.auth_token = self._create_auth_token(runner.context) updated_liveaction_db = None try: # Finalized parameters are resolved and then rendered. This process could # fail. Handle the exception and report the error correctly. runner_params, action_params = param_utils.get_finalized_params( runnertype_db.runner_parameters, action_db.parameters, liveaction_db.parameters) runner.runner_parameters = runner_params LOG.debug('Performing pre-run for runner: %s', runner) runner.pre_run() LOG.debug('Performing run for runner: %s', runner) (status, result, context) = runner.run(action_params) try: result = json.loads(result) except: pass if (isinstance(runner, AsyncActionRunner) and status not in action_constants.COMPLETED_STATES): self._setup_async_query(liveaction_db.id, runnertype_db, context) except: LOG.exception('Failed to run action.') _, ex, tb = sys.exc_info() # mark execution as failed. status = action_constants.LIVEACTION_STATUS_FAILED # include the error message and traceback to try and provide some hints. result = { 'message': str(ex), 'traceback': ''.join(traceback.format_tb(tb, 20)) } context = None finally: # Always clean-up the auth_token updated_liveaction_db = self._update_live_action_db( liveaction_db.id, status, result, context) executions.update_execution(updated_liveaction_db) LOG.debug('Updated liveaction after run: %s', updated_liveaction_db) # Deletion of the runner generated auth token is delayed until the token expires. # Async actions such as Mistral workflows uses the auth token to launch other # actions in the workflow. If the auth token is deleted here, then the actions # in the workflow will fail with unauthorized exception. if (not isinstance(runner, AsyncActionRunner) or (isinstance(runner, AsyncActionRunner) and status in action_constants.COMPLETED_STATES)): try: self._delete_auth_token(runner.auth_token) except: LOG.warn('Unable to clean-up auth_token.') LOG.debug('Performing post_run for runner: %s', runner) runner.post_run(status, result) runner.container_service = None return updated_liveaction_db
def _do_run(self, runner, runnertype_db, action_db, liveaction_db): # Create a temporary auth token which will be available # for the duration of the action execution. runner.auth_token = self._create_auth_token(runner.context) updated_liveaction_db = None try: # Finalized parameters are resolved and then rendered. This process could # fail. Handle the exception and report the error correctly. runner_params, action_params = param_utils.get_finalized_params( runnertype_db.runner_parameters, action_db.parameters, liveaction_db.parameters, liveaction_db.context) runner.runner_parameters = runner_params LOG.debug('Performing pre-run for runner: %s', runner.runner_id) runner.pre_run() # Mask secret parameters in the log context resolved_action_params = ResolvedActionParameters(action_db=action_db, runner_type_db=runnertype_db, runner_parameters=runner_params, action_parameters=action_params) extra = {'runner': runner, 'parameters': resolved_action_params} LOG.debug('Performing run for runner: %s' % (runner.runner_id), extra=extra) (status, result, context) = runner.run(action_params) try: result = json.loads(result) except: pass action_completed = status in action_constants.LIVEACTION_COMPLETED_STATES if isinstance(runner, AsyncActionRunner) and not action_completed: self._setup_async_query(liveaction_db.id, runnertype_db, context) except: LOG.exception('Failed to run action.') _, ex, tb = sys.exc_info() # mark execution as failed. status = action_constants.LIVEACTION_STATUS_FAILED # include the error message and traceback to try and provide some hints. result = {'error': str(ex), 'traceback': ''.join(traceback.format_tb(tb, 20))} context = None finally: # Log action completion extra = {'result': result, 'status': status} LOG.debug('Action "%s" completed.' % (action_db.name), extra=extra) # Always clean-up the auth_token try: LOG.debug('Setting status: %s for liveaction: %s', status, liveaction_db.id) updated_liveaction_db = self._update_live_action_db(liveaction_db.id, status, result, context) except: error = 'Cannot update LiveAction object for id: %s, status: %s, result: %s.' % ( liveaction_db.id, status, result) LOG.exception(error) raise executions.update_execution(updated_liveaction_db) extra = {'liveaction_db': updated_liveaction_db} LOG.debug('Updated liveaction after run', extra=extra) # Deletion of the runner generated auth token is delayed until the token expires. # Async actions such as Mistral workflows uses the auth token to launch other # actions in the workflow. If the auth token is deleted here, then the actions # in the workflow will fail with unauthorized exception. is_async_runner = isinstance(runner, AsyncActionRunner) action_completed = status in action_constants.LIVEACTION_COMPLETED_STATES if not is_async_runner or (is_async_runner and action_completed): try: self._delete_auth_token(runner.auth_token) except: LOG.exception('Unable to clean-up auth_token.') LOG.debug('Performing post_run for runner: %s', runner.runner_id) runner.post_run(status, result) runner.container_service = None LOG.debug('Runner do_run result', extra={'result': updated_liveaction_db.result}) LOG.audit('Liveaction completed', extra={'liveaction_db': updated_liveaction_db}) return updated_liveaction_db
def _do_run(self, runner, runnertype_db, action_db, liveaction_db): # Create a temporary auth token which will be available # for the duration of the action execution. runner.auth_token = self._create_auth_token(runner.context) updated_liveaction_db = None try: # Finalized parameters are resolved and then rendered. This process could # fail. Handle the exception and report the error correctly. runner_params, action_params = param_utils.get_finalized_params( runnertype_db.runner_parameters, action_db.parameters, liveaction_db.parameters, liveaction_db.context) runner.runner_parameters = runner_params LOG.debug('Performing pre-run for runner: %s', runner.runner_id) runner.pre_run() # Mask secret parameters in the log context resolved_action_params = ResolvedActionParameters( action_db=action_db, runner_type_db=runnertype_db, runner_parameters=runner_params, action_parameters=action_params) extra = {'runner': runner, 'parameters': resolved_action_params} LOG.debug('Performing run for runner: %s' % (runner.runner_id), extra=extra) (status, result, context) = runner.run(action_params) try: result = json.loads(result) except: pass action_completed = status in action_constants.COMPLETED_STATES if isinstance(runner, AsyncActionRunner) and not action_completed: self._setup_async_query(liveaction_db.id, runnertype_db, context) except: LOG.exception('Failed to run action.') _, ex, tb = sys.exc_info() # mark execution as failed. status = action_constants.LIVEACTION_STATUS_FAILED # include the error message and traceback to try and provide some hints. result = { 'error': str(ex), 'traceback': ''.join(traceback.format_tb(tb, 20)) } context = None finally: # Log action completion extra = {'result': result, 'status': status} LOG.debug('Action "%s" completed.' % (action_db.name), extra=extra) # Always clean-up the auth_token try: LOG.debug('Setting status: %s for liveaction: %s', status, liveaction_db.id) updated_liveaction_db = self._update_live_action_db( liveaction_db.id, status, result, context) except: error = 'Cannot update LiveAction object for id: %s, status: %s, result: %s.' % ( liveaction_db.id, status, result) LOG.exception(error) raise executions.update_execution(updated_liveaction_db) extra = {'liveaction_db': updated_liveaction_db} LOG.debug('Updated liveaction after run', extra=extra) # Deletion of the runner generated auth token is delayed until the token expires. # Async actions such as Mistral workflows uses the auth token to launch other # actions in the workflow. If the auth token is deleted here, then the actions # in the workflow will fail with unauthorized exception. is_async_runner = isinstance(runner, AsyncActionRunner) action_completed = status in action_constants.COMPLETED_STATES if not is_async_runner or (is_async_runner and action_completed): try: self._delete_auth_token(runner.auth_token) except: LOG.exception('Unable to clean-up auth_token.') LOG.debug('Performing post_run for runner: %s', runner.runner_id) runner.post_run(status, result) runner.container_service = None LOG.debug('Runner do_run result', extra={'result': updated_liveaction_db.result}) LOG.audit('Liveaction completed', extra={'liveaction_db': updated_liveaction_db}) return updated_liveaction_db
def _do_run(self, runner, runnertype_db, action_db, liveaction_db): # Finalized parameters are resolved and then rendered. runner_params, action_params = param_utils.get_finalized_params( runnertype_db.runner_parameters, action_db.parameters, liveaction_db.parameters) resolved_entry_point = self._get_entry_point_abs_path(action_db.pack, action_db.entry_point) runner.container_service = RunnerContainerService() runner.action = action_db runner.action_name = action_db.name runner.liveaction_id = str(liveaction_db.id) runner.entry_point = resolved_entry_point runner.runner_parameters = runner_params runner.context = getattr(liveaction_db, 'context', dict()) runner.callback = getattr(liveaction_db, 'callback', dict()) runner.libs_dir_path = self._get_action_libs_abs_path(action_db.pack, action_db.entry_point) runner.auth_token = self._create_auth_token(runner.context) updated_liveaction_db = None try: # Finalized parameters are resolved and then rendered. This process could # fail. Handle the exception and report the error correctly. runner_params, action_params = param_utils.get_finalized_params( runnertype_db.runner_parameters, action_db.parameters, liveaction_db.parameters) runner.runner_parameters = runner_params LOG.debug('Performing pre-run for runner: %s', runner) runner.pre_run() LOG.debug('Performing run for runner: %s', runner) (status, result, context) = runner.run(action_params) try: result = json.loads(result) except: pass if isinstance(runner, AsyncActionRunner) and status not in DONE_STATES: self._setup_async_query(liveaction_db.id, runnertype_db, context) except: LOG.exception('Failed to run action.') _, ex, tb = sys.exc_info() # mark execution as failed. status = LIVEACTION_STATUS_FAILED # include the error message and traceback to try and provide some hints. result = {'message': str(ex), 'traceback': ''.join(traceback.format_tb(tb, 20))} context = None finally: # Always clean-up the auth_token updated_liveaction_db = self._update_live_action_db(liveaction_db.id, status, result, context) executions.update_execution(updated_liveaction_db) LOG.debug('Updated liveaction after run: %s', updated_liveaction_db) try: self._delete_auth_token(runner.auth_token) except: LOG.warn('Unable to clean-up auth_token.') LOG.debug('Performing post_run for runner: %s', runner) runner.post_run(status, result) runner.container_service = None return updated_liveaction_db
def _do_run(self, runner, runnertype_db, action_db, actionexec_db): # Finalized parameters are resolved and then rendered. runner_params, action_params = param_utils.get_finalized_params( runnertype_db.runner_parameters, action_db.parameters, actionexec_db.parameters) resolved_entry_point = self._get_entry_point_abs_path(action_db.pack, action_db.entry_point) runner.container_service = RunnerContainerService() runner.action = action_db runner.action_name = action_db.name runner.action_execution_id = str(actionexec_db.id) runner.entry_point = resolved_entry_point runner.runner_parameters = runner_params runner.context = getattr(actionexec_db, 'context', dict()) runner.callback = getattr(actionexec_db, 'callback', dict()) runner.libs_dir_path = self._get_action_libs_abs_path(action_db.pack, action_db.entry_point) runner.auth_token = self._create_auth_token(runner.context) try: LOG.debug('Performing pre-run for runner: %s', runner) runner.pre_run() LOG.debug('Performing run for runner: %s', runner) run_result = runner.run(action_params) LOG.debug('Result of run: %s', run_result) except: LOG.exception('Failed to run action.') _, ex, tb = sys.exc_info() # mark execution as failed. runner.container_service.report_status(ACTIONEXEC_STATUS_FAILED) # include the error message and traceback to try and provide some hints. runner.container_service.report_result( {'message': str(ex), 'traceback': ''.join(traceback.format_tb(tb, 20))}) finally: # Always clean-up the auth_token try: self._delete_auth_token(runner.auth_token) except: LOG.warn('Unable to clean-up auth_token.') # Re-load Action Execution from DB: actionexec_db = get_actionexec_by_id(actionexec_db.id) # TODO: Store payload when DB model can hold payload data action_result = runner.container_service.get_result() actionexec_status = runner.container_service.get_status() LOG.debug('Result as reporter to container service: %s', action_result) if action_result is None: # If the runner didn't set an exit code then the action didn't complete. # Therefore, the action produced an error. result = False if not actionexec_status: actionexec_status = ACTIONEXEC_STATUS_FAILED runner.container_service.report_status(actionexec_status) else: # So long as the runner produced an exit code, we can assume that the # Live Action ran to completion. result = True actionexec_db.result = action_result if not actionexec_status: actionexec_status = ACTIONEXEC_STATUS_SUCCEEDED runner.container_service.report_status(actionexec_status) # Push result data and updated status to ActionExecution DB actionexec_db = update_actionexecution_status(actionexec_status, actionexec_db=actionexec_db) LOG.debug('Performing post_run for runner: %s', runner) runner.post_run() runner.container_service = None return result, actionexec_db
def _do_run(self, runner, runnertype_db, action_db, actionexec_db): resolved_entry_point = self._get_entry_point_abs_path( action_db.pack, action_db.entry_point) runner.container_service = RunnerContainerService() runner.action = action_db runner.action_name = action_db.name runner.action_execution_id = str(actionexec_db.id) runner.entry_point = resolved_entry_point runner.context = getattr(actionexec_db, 'context', dict()) runner.callback = getattr(actionexec_db, 'callback', dict()) runner.libs_dir_path = self._get_action_libs_abs_path( action_db.pack, action_db.entry_point) runner.auth_token = self._create_auth_token(runner.context) updated_actionexec_db = None try: # Finalized parameters are resolved and then rendered. This process could # fail. Handle the exception and report the error correctly. runner_params, action_params = param_utils.get_finalized_params( runnertype_db.runner_parameters, action_db.parameters, actionexec_db.parameters) runner.runner_parameters = runner_params LOG.debug('Performing pre-run for runner: %s', runner) runner.pre_run() LOG.debug('Performing run for runner: %s', runner) if isinstance(runner, AsyncActionRunner): (status, result, query_context) = runner.run(action_params) else: (status, result) = runner.run(action_params) try: result = json.loads(result) except: pass if status not in DONE_STATES: self._setup_async_query(actionexec_db.id, runnertype_db, query_context) except: LOG.exception('Failed to run action.') _, ex, tb = sys.exc_info() # mark execution as failed. status = ACTIONEXEC_STATUS_FAILED # include the error message and traceback to try and provide some hints. result = { 'message': str(ex), 'traceback': ''.join(traceback.format_tb(tb, 20)) } finally: # Always clean-up the auth_token updated_actionexec_db = self._update_action_execution_db( actionexec_db.id, status, result) LOG.debug('Updated ActionExecution after run: %s', updated_actionexec_db) try: self._delete_auth_token(runner.auth_token) except: LOG.warn('Unable to clean-up auth_token.') LOG.debug('Performing post_run for runner: %s', runner) runner.post_run(status, result) runner.container_service = None return updated_actionexec_db