def test_get_entry_point_absolute_path_empty(self): orig_path = cfg.CONF.content.system_packs_base_path cfg.CONF.content.system_packs_base_path = '/tests/packs' acutal_path = get_entry_point_abs_path(pack='foo', entry_point=None) self.assertEqual(acutal_path, None, 'Entry point path doesn\'t match.') acutal_path = get_entry_point_abs_path(pack='foo', entry_point='') self.assertEqual(acutal_path, None, 'Entry point path doesn\'t match.') cfg.CONF.content.system_packs_base_path = orig_path
def get_one(self, ref_or_id, requester_user): """ Outputs the file associated with action entry_point Handles requests: GET /actions/views/entry_point/1 """ LOG.info('GET /actions/views/entry_point with ref_or_id=%s', ref_or_id) action_db = self._get_by_ref_or_id(ref_or_id=ref_or_id) permission_type = PermissionType.ACTION_VIEW rbac_utils.assert_user_has_resource_db_permission(user_db=requester_user, resource_db=action_db, permission_type=permission_type) pack = getattr(action_db, 'pack', None) entry_point = getattr(action_db, 'entry_point', None) abs_path = utils.get_entry_point_abs_path(pack, entry_point) if not abs_path: raise StackStormDBObjectNotFoundError('Action ref_or_id=%s has no entry_point to output' % ref_or_id) with open(abs_path) as file: content = file.read() return content
def get_one(self, ref_or_id, requester_user): """ Outputs the file associated with action entry_point Handles requests: GET /actions/views/entry_point/1 """ LOG.info('GET /actions/views/entry_point with ref_or_id=%s', ref_or_id) action_db = self._get_by_ref_or_id(ref_or_id=ref_or_id) permission_type = PermissionType.ACTION_VIEW rbac_utils.assert_user_has_resource_db_permission( user_db=requester_user, resource_db=action_db, permission_type=permission_type) pack = getattr(action_db, 'pack', None) entry_point = getattr(action_db, 'entry_point', None) abs_path = utils.get_entry_point_abs_path(pack, entry_point) if not abs_path: raise StackStormDBObjectNotFoundError( 'Action ref_or_id=%s has no entry_point to output' % ref_or_id) with open(abs_path) as file: content = file.read() return content
def invoke_post_run(liveaction_db, action_db=None): LOG.info('Invoking post run for action execution %s.', liveaction_db.id) # Identify action and runner. if not action_db: action_db = action_db_utils.get_action_by_ref(liveaction_db.action) if not action_db: LOG.exception('Unable to invoke post run. Action %s no longer exists.', liveaction_db.action) return LOG.info('Action execution %s runs %s of runner type %s.', liveaction_db.id, action_db.name, action_db.runner_type['name']) # Get an instance of the action runner. runnertype_db = action_db_utils.get_runnertype_by_name( action_db.runner_type['name']) runner = runners.get_runner(runnertype_db.runner_module) # Configure the action runner. runner.action = action_db runner.action_name = action_db.name runner.action_execution_id = str(liveaction_db.id) runner.entry_point = content_utils.get_entry_point_abs_path( pack=action_db.pack, entry_point=action_db.entry_point) runner.context = getattr(liveaction_db, 'context', dict()) runner.callback = getattr(liveaction_db, 'callback', dict()) runner.libs_dir_path = content_utils.get_action_libs_abs_path( pack=action_db.pack, entry_point=action_db.entry_point) # Invoke the post_run method. runner.post_run(liveaction_db.status, liveaction_db.result)
def test_get_entry_point_relative_path(self): orig_path = cfg.CONF.content.system_packs_base_path cfg.CONF.content.system_packs_base_path = '/tests/packs' acutal_path = get_entry_point_abs_path(pack='foo', entry_point='foo/bar.py') expected_path = os.path.join(cfg.CONF.content.system_packs_base_path, 'foo', 'actions', 'foo/bar.py') self.assertEqual(acutal_path, expected_path, 'Entry point path doesn\'t match.') cfg.CONF.content.system_packs_base_path = orig_path
def get_one(self, ref_or_id, requester_user): """ Outputs the file associated with action entry_point Handles requests: GET /actions/views/entry_point/1 """ LOG.info("GET /actions/views/entry_point with ref_or_id=%s", ref_or_id) action_db = self._get_by_ref_or_id(ref_or_id=ref_or_id) permission_type = PermissionType.ACTION_VIEW rbac_utils = get_rbac_backend().get_utils_class() rbac_utils.assert_user_has_resource_db_permission( user_db=requester_user, resource_db=action_db, permission_type=permission_type, ) pack = getattr(action_db, "pack", None) entry_point = getattr(action_db, "entry_point", None) abs_path = utils.get_entry_point_abs_path(pack, entry_point) if not abs_path: raise StackStormDBObjectNotFoundError( "Action ref_or_id=%s has no entry_point to output" % ref_or_id) with codecs.open(abs_path, "r") as fp: content = fp.read() # Ensure content is utf-8 if isinstance(content, six.binary_type): content = content.decode("utf-8") try: content_type = mimetypes.guess_type(abs_path)[0] except Exception: content_type = None # Special case if /etc/mime.types doesn't contain entry for yaml, py if not content_type: _, extension = os.path.splitext(abs_path) if extension in [".yaml", ".yml"]: content_type = "application/x-yaml" elif extension in [".py"]: content_type = "application/x-python" else: content_type = "text/plain" response = Response() response.headers["Content-Type"] = content_type response.text = content return response
def invoke_post_run(liveaction_db, action_db=None): # NOTE: This import has intentionally been moved here to avoid massive performance overhead # (1+ second) for other functions inside this module which don't need to use those imports. from st2common.runners import base as runners from st2common.util import action_db as action_db_utils from st2common.content import utils as content_utils LOG.info("Invoking post run for action execution %s.", liveaction_db.id) # Identify action and runner. if not action_db: action_db = action_db_utils.get_action_by_ref(liveaction_db.action) if not action_db: LOG.error( "Unable to invoke post run. Action %s no longer exists.", liveaction_db.action, ) return LOG.info( "Action execution %s runs %s of runner type %s.", liveaction_db.id, action_db.name, action_db.runner_type["name"], ) # Get instance of the action runner and related configuration. runner_type_db = action_db_utils.get_runnertype_by_name( action_db.runner_type["name"]) runner = runners.get_runner(name=runner_type_db.name) entry_point = content_utils.get_entry_point_abs_path( pack=action_db.pack, entry_point=action_db.entry_point) libs_dir_path = content_utils.get_action_libs_abs_path( pack=action_db.pack, entry_point=action_db.entry_point) # Configure the action runner. runner.runner_type_db = runner_type_db runner.action = action_db runner.action_name = action_db.name runner.liveaction = liveaction_db runner.liveaction_id = str(liveaction_db.id) runner.entry_point = entry_point runner.context = getattr(liveaction_db, "context", dict()) runner.callback = getattr(liveaction_db, "callback", dict()) runner.libs_dir_path = libs_dir_path # Invoke the post_run method. runner.post_run(liveaction_db.status, liveaction_db.result)
def get_one(self, ref_or_id, requester_user): """ Outputs the file associated with action entry_point Handles requests: GET /actions/views/entry_point/1 """ LOG.info('GET /actions/views/entry_point with ref_or_id=%s', ref_or_id) action_db = self._get_by_ref_or_id(ref_or_id=ref_or_id) permission_type = PermissionType.ACTION_VIEW rbac_utils = get_rbac_backend().get_utils_class() rbac_utils.assert_user_has_resource_db_permission(user_db=requester_user, resource_db=action_db, permission_type=permission_type) pack = getattr(action_db, 'pack', None) entry_point = getattr(action_db, 'entry_point', None) abs_path = utils.get_entry_point_abs_path(pack, entry_point) if not abs_path: raise StackStormDBObjectNotFoundError('Action ref_or_id=%s has no entry_point to output' % ref_or_id) with codecs.open(abs_path, 'r') as fp: content = fp.read() # Ensure content is utf-8 if isinstance(content, six.binary_type): content = content.decode('utf-8') try: content_type = mimetypes.guess_type(abs_path)[0] except Exception: content_type = None # Special case if /etc/mime.types doesn't contain entry for yaml, py if not content_type: _, extension = os.path.splitext(abs_path) if extension in ['.yaml', '.yml']: content_type = 'application/x-yaml' elif extension in ['.py']: content_type = 'application/x-python' else: content_type = 'text/plain' response = Response() response.headers['Content-Type'] = content_type response.text = content return response
def get_one(self, ref_or_id): """ Outputs the file associated with action entry_point Handles requests: GET /actions/views/entry_point/1 """ LOG.info('GET /actions/views/overview with ref_or_id=%s', ref_or_id) action_db = self._get_by_ref_or_id(ref_or_id=ref_or_id) pack = getattr(action_db, 'pack', None) entry_point = getattr(action_db, 'entry_point', None) abs_path = utils.get_entry_point_abs_path(pack, entry_point) if not abs_path: raise StackStormDBObjectNotFoundError( 'Action ref_or_id=%s has no entry_point to output' % ref_or_id) with open(abs_path) as file: content = file.read() return content
def get_one(self, ref_or_id): """ Outputs the file associated with action entry_point Handles requests: GET /actions/views/entry_point/1 """ LOG.info('GET /actions/views/overview with ref_or_id=%s', ref_or_id) action_db = self._get_by_ref_or_id(ref_or_id=ref_or_id) pack = getattr(action_db, 'pack', None) entry_point = getattr(action_db, 'entry_point', None) abs_path = utils.get_entry_point_abs_path(pack, entry_point) if not abs_path: raise StackStormDBObjectNotFoundError('Action ref_or_id=%s has no entry_point to output' % ref_or_id) with open(abs_path) as file: content = file.read() return content
def get_entry_point_abs_path(pack=None, entry_point=None): return utils.get_entry_point_abs_path(pack, entry_point)
def _get_entry_point_abs_path(self, pack, entry_point): return content_utils.get_entry_point_abs_path(pack=pack, entry_point=entry_point)
def main(): # Read DEBUG value from the environment variable debug = os.environ.get('ST2_DEBUG', False) if str(debug).lower() in ['true', '1']: debug = True if debug: LOG.setLevel(logging.DEBUG) else: LOG.setLevel(logging.INFO) # Read input = os.environ.get('ST2_INPUT', {}) if isinstance(input, six.string_types): try: input = json.loads(input) except ValueError as e: LOG.error("ERROR: Can not parse `input`: '{}'\n{}".format(str(input), str(e))) raise e LOG.debug("Received input: " + json.dumps(input, indent=2)) # Read action name from environment variable action_name = os.environ['ST2_ACTION'] try: action_db = ACTIONS[action_name] except KeyError: raise ValueError('No action named "%s" has been installed.' % (action_name)) # Initialize runner manager = DriverManager(namespace='st2common.runners.runner', invoke_on_load=False, name=action_db.runner_type['name']) runnertype_db = RunnerTypeAPI.to_model(RunnerTypeAPI(**manager.driver.get_metadata())) runner = manager.driver.get_runner() runner._sandbox = False runner.runner_type_db = runnertype_db runner.action = action_db runner.action_name = action_db.name runner.entry_point = content_utils.get_entry_point_abs_path(pack=action_db.pack, entry_point=action_db.entry_point) runner.context = {} runner.libs_dir_path = content_utils.get_action_libs_abs_path(pack=action_db.pack, entry_point=action_db.entry_point) config_schema = CONFIG_SCHEMAS.get(action_db.pack, None) config_values = os.environ.get('ST2_CONFIG', None) if config_schema and config_values: runner._config = validate_config_against_schema(config_schema=config_schema, config_object=json.loads(config_values), config_path=None, pack_name=action_db.pack) param_values = os.environ.get('ST2_PARAMETERS', None) try: if param_values: live_params = param_utils.render_live_params( runner_parameters=runnertype_db.runner_parameters, action_parameters=action_db.parameters, params=json.loads(param_values), action_context={}, additional_contexts={ 'input': input }) else: live_params = input if debug and 'log_level' not in live_params: # Set log_level runner parameter live_params['log_level'] = 'DEBUG' runner_params, action_params = param_utils.render_final_params( runner_parameters=runnertype_db.runner_parameters, action_parameters=action_db.parameters, params=live_params, action_context={}) except ParamException as e: raise actionrunner.ActionRunnerException(str(e)) runner.runner_parameters = runner_params LOG.debug('Performing pre-run for runner: %s', runner.runner_id) runner.pre_run() (status, output, context) = runner.run(action_params) try: output['result'] = json.loads(output['result']) except Exception: pass output_values = os.environ.get('ST2_OUTPUT', None) if output_values: try: result = param_utils.render_live_params( runner_parameters={}, action_parameters={}, params=json.loads(output_values), action_context={}, additional_contexts={ 'input': input, 'output': output }) except ParamException as e: raise actionrunner.ActionRunnerException(str(e)) else: result = output output = output or {} if output.get('stdout', None): LOG.info('Action stdout: %s' % (output['stdout'])) if output.get('stderr', None): LOG.info('Action stderr and logs: %s' % (output['stderr'])) print(json.dumps(result))
def base(event, context, passthrough=False): # Set up logging logger = logging.getLogger() # Read DEBUG value from the environment variable debug = os.environ.get('ST2_DEBUG', False) if str(debug).lower() in ['true', '1']: debug = True if debug: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) if isinstance(event, basestring): try: event = json.loads(event) except ValueError as e: LOG.error("ERROR: Can not parse `event`: '{}'\n{}".format( str(event), str(e))) raise e LOG.info("Received event: " + json.dumps(event, indent=2)) # Special case for Lambda function being called over HTTP via API gateway # See # https://serverless.com/framework/docs/providers/aws/events/apigateway # #example-lambda-proxy-event-default # for details is_event_body_string = (isinstance(event.get('body'), basestring) is True) content_type = event.get('headers', {}).get('content-type', '').lower() if is_event_body_string: if content_type == 'application/json': try: event['body'] = json.loads(event['body']) except Exception as e: LOG.warn('`event` has `body` which is not JSON: %s', str(e.message)) elif content_type == 'application/x-www-form-urlencoded': try: event['body'] = dict( parse_qsl(['body'], keep_blank_values=True)) except Exception as e: LOG.warn('`event` has `body` which is not `%s`: %s', content_type, str(e.message)) else: LOG.warn('Unsupported event content type: %s' % (content_type)) action_name = os.environ['ST2_ACTION'] try: action_db = ACTIONS[action_name] except KeyError: raise ValueError('No action named "%s" has been installed.' % (action_name)) manager = DriverManager(namespace='st2common.runners.runner', invoke_on_load=False, name=action_db.runner_type['name']) runnertype_db = RunnerTypeAPI.to_model( RunnerTypeAPI(**manager.driver.get_metadata()[0])) if passthrough: runner = PassthroughRunner() else: runner = manager.driver.get_runner() runner._sandbox = False runner.runner_type_db = runnertype_db runner.action = action_db runner.action_name = action_db.name # runner.liveaction = liveaction_db # runner.liveaction_id = str(liveaction_db.id) # runner.execution = ActionExecution.get(liveaction__id=runner.liveaction_id) # runner.execution_id = str(runner.execution.id) runner.entry_point = content_utils.get_entry_point_abs_path( pack=action_db.pack, entry_point=action_db.entry_point) runner.context = {} # getattr(liveaction_db, 'context', dict()) # runner.callback = getattr(liveaction_db, 'callback', dict()) runner.libs_dir_path = content_utils.get_action_libs_abs_path( pack=action_db.pack, entry_point=action_db.entry_point) # For re-run, get the ActionExecutionDB in which the re-run is based on. # rerun_ref_id = runner.context.get('re-run', {}).get('ref') # runner.rerun_ex_ref = ActionExecution.get(id=rerun_ref_id) if rerun_ref_id else None config_schema = CONFIG_SCHEMAS.get(action_db.pack, None) config_values = os.environ.get('ST2_CONFIG', None) if config_schema and config_values: runner._config = validate_config_against_schema( config_schema=config_schema, config_object=json.loads(config_values), config_path=None, pack_name=action_db.pack) param_values = os.environ.get('ST2_PARAMETERS', None) try: if param_values: live_params = param_utils.render_live_params( runner_parameters=runnertype_db.runner_parameters, action_parameters=action_db.parameters, params=json.loads(param_values), action_context={}, additional_contexts={'input': event}) else: live_params = event if debug and 'log_level' not in live_params: # Set log_level runner parameter live_params['log_level'] = 'DEBUG' runner_params, action_params = param_utils.render_final_params( runner_parameters=runnertype_db.runner_parameters, action_parameters=action_db.parameters, params=live_params, action_context={}) except ParamException as e: raise actionrunner.ActionRunnerException(str(e)) runner.runner_parameters = runner_params LOG.debug('Performing pre-run for runner: %s', runner.runner_id) runner.pre_run() (status, output, context) = runner.run(action_params) output_values = os.environ.get('ST2_OUTPUT', None) if output_values: try: result = param_utils.render_live_params( runner_parameters=runnertype_db.runner_parameters, action_parameters=action_db.parameters, params=json.loads(output_values), action_context={}, additional_contexts={ 'input': event, 'output': output }) except ParamException as e: raise actionrunner.ActionRunnerException(str(e)) else: result = output # Log the logs generated by the action. We do that so the actual action logs # (action stderr) end up in CloudWatch output = output or {} if output.get('stdout', None): LOG.info('Action stdout: %s' % (output['stdout'])) if output.get('stderr', None): LOG.info('Action stderr and logs: %s' % (output['stderr'])) return { 'event': event, 'live_params': live_params, 'output': output, 'result': result }