mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Merge pull request #747 from YunoHost/python-hooks-reloaded
Python hooks reloaded
This commit is contained in:
commit
a208763d0c
1 changed files with 59 additions and 23 deletions
|
@ -25,8 +25,11 @@
|
|||
"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import tempfile
|
||||
import mimetypes
|
||||
from glob import iglob
|
||||
from importlib import import_module
|
||||
|
||||
from moulinette import m18n, msettings
|
||||
from yunohost.utils.error import YunohostError
|
||||
|
@ -179,7 +182,7 @@ def hook_list(action, list_by='name', show_info=False):
|
|||
def _append_folder(d, folder):
|
||||
# Iterate over and add hook from a folder
|
||||
for f in os.listdir(folder + action):
|
||||
if f[0] == '.' or f[-1] == '~':
|
||||
if f[0] == '.' or f[-1] == '~' or f.endswith(".pyc"):
|
||||
continue
|
||||
path = '%s%s/%s' % (folder, action, f)
|
||||
priority, name = _extract_filename_parts(f)
|
||||
|
@ -311,7 +314,6 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
|
|||
user -- User with which to run the command
|
||||
|
||||
"""
|
||||
from moulinette.utils.process import call_async_output
|
||||
|
||||
# Validate hook path
|
||||
if path[0] != '/':
|
||||
|
@ -319,6 +321,38 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
|
|||
if not os.path.isfile(path):
|
||||
raise YunohostError('file_does_not_exist', path=path)
|
||||
|
||||
# Define output loggers and call command
|
||||
loggers = (
|
||||
lambda l: logger.debug(l.rstrip()+"\r"),
|
||||
lambda l: logger.warning(l.rstrip()),
|
||||
lambda l: logger.info(l.rstrip())
|
||||
)
|
||||
|
||||
# Check the type of the hook (bash by default)
|
||||
# For now we support only python and bash hooks.
|
||||
hook_type = mimetypes.MimeTypes().guess_type(path)[0]
|
||||
if hook_type == 'text/x-python':
|
||||
returncode, returndata = _hook_exec_python(path, args, env, loggers)
|
||||
else:
|
||||
returncode, returndata = _hook_exec_bash(path, args, no_trace, chdir, env, user, return_format, loggers)
|
||||
|
||||
# Check and return process' return code
|
||||
if returncode is None:
|
||||
if raise_on_error:
|
||||
raise YunohostError('hook_exec_not_terminated', path=path)
|
||||
else:
|
||||
logger.error(m18n.n('hook_exec_not_terminated', path=path))
|
||||
return 1, {}
|
||||
elif raise_on_error and returncode != 0:
|
||||
raise YunohostError('hook_exec_failed', path=path)
|
||||
|
||||
return returncode, returndata
|
||||
|
||||
|
||||
def _hook_exec_bash(path, args, no_trace, chdir, env, user, return_format, loggers):
|
||||
|
||||
from moulinette.utils.process import call_async_output
|
||||
|
||||
# Construct command variables
|
||||
cmd_args = ''
|
||||
if args and isinstance(args, list):
|
||||
|
@ -369,33 +403,13 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
|
|||
else:
|
||||
logger.debug(m18n.n('executing_script', script=path))
|
||||
|
||||
# Define output callbacks and call command
|
||||
callbacks = (
|
||||
lambda l: logger.debug(l.rstrip()+"\r"),
|
||||
lambda l: logger.warning(l.rstrip()),
|
||||
)
|
||||
|
||||
if stdinfo:
|
||||
callbacks = (callbacks[0], callbacks[1],
|
||||
lambda l: logger.info(l.rstrip()))
|
||||
|
||||
logger.debug("About to run the command '%s'" % command)
|
||||
|
||||
returncode = call_async_output(
|
||||
command, callbacks, shell=False, cwd=chdir,
|
||||
command, loggers, shell=False, cwd=chdir,
|
||||
stdinfo=stdinfo
|
||||
)
|
||||
|
||||
# Check and return process' return code
|
||||
if returncode is None:
|
||||
if raise_on_error:
|
||||
raise YunohostError('hook_exec_not_terminated', path=path)
|
||||
else:
|
||||
logger.error(m18n.n('hook_exec_not_terminated', path=path))
|
||||
return 1, {}
|
||||
elif raise_on_error and returncode != 0:
|
||||
raise YunohostError('hook_exec_failed', path=path)
|
||||
|
||||
raw_content = None
|
||||
try:
|
||||
with open(stdreturn, 'r') as f:
|
||||
|
@ -427,6 +441,25 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False,
|
|||
return returncode, returncontent
|
||||
|
||||
|
||||
def _hook_exec_python(path, args, env, loggers):
|
||||
|
||||
dir_ = os.path.dirname(path)
|
||||
name = os.path.splitext(os.path.basename(path))[0]
|
||||
|
||||
if not dir_ in sys.path:
|
||||
sys.path = [dir_] + sys.path
|
||||
module = import_module(name)
|
||||
|
||||
ret = module.main(args, env, loggers)
|
||||
# # Assert that the return is a (int, dict) tuple
|
||||
assert isinstance(ret, tuple) \
|
||||
and len(ret) == 2 \
|
||||
and isinstance(ret[0],int) \
|
||||
and isinstance(ret[1],dict), \
|
||||
"Module %s did not return a (int, dict) tuple !" % module
|
||||
return ret
|
||||
|
||||
|
||||
def _extract_filename_parts(filename):
|
||||
"""Extract hook parts from filename"""
|
||||
if '-' in filename:
|
||||
|
@ -434,6 +467,9 @@ def _extract_filename_parts(filename):
|
|||
else:
|
||||
priority = '50'
|
||||
action = filename
|
||||
|
||||
# Remove extension if there's one
|
||||
action = os.path.splitext(action)[0]
|
||||
return priority, action
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue