<s> import os <EOL> import os . path <EOL> import six <EOL> from pecan import abort <EOL> from mongoengine import ValidationError <EOL> from st2api . controllers import resource <EOL> from st2api . controllers . v1 . actionviews import ActionViewsController <EOL> from st2common import log as logging <EOL> from st2common . constants . triggers import ACTION_FILE_WRITTEN_TRIGGER <EOL> from st2common . exceptions . action import InvalidActionParameterException <EOL> from st2common . exceptions . apivalidation import ValueValidationException <EOL> from st2common . models . api . base import jsexpose <EOL> from st2common . persistence . action import Action <EOL> from st2common . models . api . action import ActionAPI <EOL> from st2common . models . api . action import ActionCreateAPI <EOL> from st2common . persistence . pack import Pack <EOL> from st2common . validators . api . misc import validate_not_part_of_system_pack <EOL> from st2common . content . utils import get_pack_base_path <EOL> from st2common . content . utils import get_pack_resource_file_abs_path <EOL> from st2common . content . utils import get_relative_path_to_pack <EOL> from st2common . transport . reactor import TriggerDispatcher <EOL> from st2common . util . system_info import get_host_info <EOL> import st2common . validators . api . action as action_validator <EOL> from st2common . rbac . types import PermissionType <EOL> from st2common . rbac . decorators import request_user_has_permission <EOL> from st2common . rbac . decorators import request_user_has_resource_api_permission <EOL> from st2common . rbac . decorators import request_user_has_resource_db_permission <EOL> http_client = six . moves . http_client <EOL> LOG = logging . getLogger ( __name__ ) <EOL> class ActionsController ( resource . ContentPackResourceController ) : <EOL> """<STR_LIT>""" <EOL> views = ActionViewsController ( ) <EOL> model = ActionAPI <EOL> access = Action <EOL> supported_filters = { <EOL> '<STR_LIT:name>' : '<STR_LIT:name>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> } <EOL> query_options = { <EOL> '<STR_LIT>' : [ '<STR_LIT>' , '<STR_LIT:name>' ] <EOL> } <EOL> include_reference = True <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( ActionsController , self ) . __init__ ( * args , ** kwargs ) <EOL> self . _trigger_dispatcher = TriggerDispatcher ( LOG ) <EOL> @ request_user_has_permission ( permission_type = PermissionType . ACTION_LIST ) <EOL> @ jsexpose ( ) <EOL> def get_all ( self , ** kwargs ) : <EOL> return super ( ActionsController , self ) . _get_all ( ** kwargs ) <EOL> @ request_user_has_resource_db_permission ( permission_type = PermissionType . ACTION_VIEW ) <EOL> @ jsexpose ( arg_types = [ str ] ) <EOL> def get_one ( self , ref_or_id ) : <EOL> return super ( ActionsController , self ) . _get_one ( ref_or_id ) <EOL> @ jsexpose ( body_cls = ActionCreateAPI , status_code = http_client . CREATED ) <EOL> @ request_user_has_resource_api_permission ( permission_type = PermissionType . ACTION_CREATE ) <EOL> def post ( self , action ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> validate_not_part_of_system_pack ( action ) <EOL> action_validator . validate_action ( action ) <EOL> except ( ValidationError , ValueError , <EOL> ValueValidationException , InvalidActionParameterException ) as e : <EOL> LOG . exception ( '<STR_LIT>' , action ) <EOL> abort ( http_client . BAD_REQUEST , str ( e ) ) <EOL> return <EOL> data_files = getattr ( action , '<STR_LIT>' , [ ] ) <EOL> written_data_files = [ ] <EOL> if data_files : <EOL> written_data_files = self . _handle_data_files ( pack_name = action . pack , <EOL> data_files = data_files ) <EOL> action_model = ActionAPI . to_model ( action ) <EOL> LOG . debug ( '<STR_LIT>' , action ) <EOL> action_db = Action . add_or_update ( action_model ) <EOL> LOG . debug ( '<STR_LIT>' , action_db ) <EOL> if written_data_files : <EOL> self . _dispatch_trigger_for_written_data_files ( action_db = action_db , <EOL> written_data_files = written_data_files ) <EOL> extra = { '<STR_LIT>' : action_db } <EOL> LOG . audit ( '<STR_LIT>' % ( action_db . id ) , extra = extra ) <EOL> action_api = ActionAPI . from_model ( action_db ) <EOL> return action_api <EOL> @ request_user_has_resource_db_permission ( permission_type = PermissionType . ACTION_MODIFY ) <EOL> @ jsexpose ( arg_types = [ str ] , body_cls = ActionCreateAPI ) <EOL> def put ( self , action_ref_or_id , action ) : <EOL> action_db = self . _get_by_ref_or_id ( ref_or_id = action_ref_or_id ) <EOL> action_id = action_db . id <EOL> if not getattr ( action , '<STR_LIT>' , None ) : <EOL> action . pack = action_db . pack <EOL> validate_not_part_of_system_pack ( action ) <EOL> action_validator . validate_action ( action ) <EOL> data_files = getattr ( action , '<STR_LIT>' , [ ] ) <EOL> written_data_files = [ ] <EOL> if data_files : <EOL> written_data_files = self . _handle_data_files ( pack_name = action . pack , <EOL> data_files = data_files ) <EOL> try : <EOL> action_db = ActionAPI . to_model ( action ) <EOL> LOG . debug ( '<STR_LIT>' , action_db ) <EOL> action_db . id = action_id <EOL> action_db = Action . add_or_update ( action_db ) <EOL> LOG . debug ( '<STR_LIT>' , action_db ) <EOL> except ( ValidationError , ValueError ) as e : <EOL> LOG . exception ( '<STR_LIT>' , action ) <EOL> abort ( http_client . BAD_REQUEST , str ( e ) ) <EOL> return <EOL> if written_data_files : <EOL> self . _dispatch_trigger_for_written_data_files ( action_db = action_db , <EOL> written_data_files = written_data_files ) <EOL> action_api = ActionAPI . from_model ( action_db ) <EOL> LOG . debug ( '<STR_LIT>' , action_api ) <EOL> return action_api <EOL> @ request_user_has_resource_db_permission ( permission_type = PermissionType . ACTION_DELETE ) <EOL> @ jsexpose ( arg_types = [ str ] , status_code = http_client . NO_CONTENT ) <EOL> def delete ( self , action_ref_or_id ) : <EOL> """<STR_LIT>""" <EOL> action_db = self . _get_by_ref_or_id ( ref_or_id = action_ref_or_id ) <EOL> action_id = action_db . id <EOL> try : <EOL> validate_not_part_of_system_pack ( action_db ) <EOL> except ValueValidationException as e : <EOL> abort ( http_client . BAD_REQUEST , str ( e ) ) <EOL> LOG . debug ( '<STR_LIT>' , <EOL> action_ref_or_id , action_db ) <EOL> try : <EOL> Action . delete ( action_db ) <EOL> except Exception as e : <EOL> LOG . error ( '<STR_LIT>' <EOL> '<STR_LIT>' , action_id , e ) <EOL> abort ( http_client . INTERNAL_SERVER_ERROR , str ( e ) ) <EOL> return <EOL> extra = { '<STR_LIT>' : action_db } <EOL> LOG . audit ( '<STR_LIT>' % ( action_db . id ) , extra = extra ) <EOL> return None <EOL> def _handle_data_files ( self , pack_name , data_files ) : <EOL> """<STR_LIT>""" <EOL> written_file_paths = self . _write_data_files_to_disk ( pack_name = pack_name , <EOL> data_files = data_files ) <EOL> self . _update_pack_model ( pack_name = pack_name , data_files = data_files , <EOL> written_file_paths = written_file_paths ) <EOL> return written_file_paths <EOL> def _write_data_files_to_disk ( self , pack_name , data_files ) : <EOL> """<STR_LIT>""" <EOL> written_file_paths = [ ] <EOL> for data_file in data_files : <EOL> file_path = data_file [ '<STR_LIT>' ] <EOL> content = data_file [ '<STR_LIT:content>' ] <EOL> file_path = get_pack_resource_file_abs_path ( pack_name = pack_name , <EOL> resource_type = '<STR_LIT:action>' , <EOL> file_path = file_path ) <EOL> LOG . debug ( '<STR_LIT>' % ( str ( data_file ) , file_path ) ) <EOL> self . _write_data_file ( pack_name = pack_name , file_path = file_path , content = content ) <EOL> written_file_paths . append ( file_path ) <EOL> return written_file_paths <EOL> def _update_pack_model ( self , pack_name , data_files , written_file_paths ) : <EOL> """<STR_LIT>""" <EOL> file_paths = [ ] <EOL> for file_path in written_file_paths : <EOL> file_path = get_relative_path_to_pack ( pack_name = pack_name , file_path = file_path ) <EOL> file_paths . append ( file_path ) <EOL> pack_db = Pack . get_by_ref ( pack_name ) <EOL> pack_db . files = set ( pack_db . files ) <EOL> pack_db . files . update ( set ( file_paths ) ) <EOL> pack_db . files = list ( pack_db . files ) <EOL> pack_db = Pack . add_or_update ( pack_db ) <EOL> return pack_db <EOL> def _write_data_file ( self , pack_name , file_path , content ) : <EOL> """<STR_LIT>""" <EOL> pack_base_path = get_pack_base_path ( pack_name = pack_name ) <EOL> if not os . path . isdir ( pack_base_path ) : <EOL> raise ValueError ( '<STR_LIT>' % ( pack_name ) ) <EOL> directory = os . path . dirname ( file_path ) <EOL> if not os . path . isdir ( directory ) : <EOL> os . makedirs ( directory ) <EOL> with open ( file_path , '<STR_LIT:w>' ) as fp : <EOL> fp . write ( content ) <EOL> def _dispatch_trigger_for_written_data_files ( self , action_db , written_data_files ) : <EOL> trigger = ACTION_FILE_WRITTEN_TRIGGER [ '<STR_LIT:name>' ] <EOL> host_info = get_host_info ( ) <EOL> for file_path in written_data_files : <EOL> payload = { <EOL> '<STR_LIT>' : action_db . ref , <EOL> '<STR_LIT>' : file_path , <EOL> '<STR_LIT>' : host_info <EOL> } <EOL> self . _trigger_dispatcher . dispatch ( trigger = trigger , payload = payload ) </s>
