Clean usr/bin/yunohost and yunohost-api ...

This commit is contained in:
Alexandre Aubin 2020-04-07 20:24:04 +02:00
parent 9962fd610e
commit 94d0e253f7
2 changed files with 52 additions and 163 deletions

View file

@ -5,36 +5,13 @@ import os
import sys import sys
import argparse import argparse
# Either we are in a development environment or not
IN_DEVEL = False
# Level for which loggers will log
LOGGERS_LEVEL = 'DEBUG'
TTY_LOG_LEVEL = 'INFO'
# Handlers that will be used by loggers
# - file: log to the file LOG_DIR/LOG_FILE
# - tty: log to current tty
LOGGERS_HANDLERS = ['file', 'tty']
# Directory and file to be used by logging
LOG_DIR = '/var/log/yunohost'
LOG_FILE = 'yunohost-cli.log'
# Check and load - as needed - development environment
if not __file__.startswith('/usr/'):
IN_DEVEL = True
if IN_DEVEL:
basedir = os.path.abspath('%s/../' % os.path.dirname(__file__))
if os.path.isdir(os.path.join(basedir, 'moulinette')):
sys.path.insert(0, basedir)
LOG_DIR = os.path.join(basedir, 'log')
import moulinette import moulinette
from moulinette.actionsmap import ActionsMap from moulinette.actionsmap import ActionsMap
from moulinette.interfaces.cli import colorize, get_locale from moulinette.interfaces.cli import colorize, get_locale
# Directory and file to be used by logging
LOG_DIR = '/var/log/yunohost'
LOG_FILE = 'yunohost-cli.log'
# Initialization & helpers functions ----------------------------------- # Initialization & helpers functions -----------------------------------
@ -46,10 +23,6 @@ def _die(message, title='Error:'):
def _parse_cli_args(): def _parse_cli_args():
"""Parse additional arguments for the cli""" """Parse additional arguments for the cli"""
parser = argparse.ArgumentParser(add_help=False) parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('--no-cache',
action='store_false', default=True, dest='use_cache',
help="Don't use actions map cache",
)
parser.add_argument('--output-as', parser.add_argument('--output-as',
choices=['json', 'plain', 'none'], default=None, choices=['json', 'plain', 'none'], default=None,
help="Output result in another format", help="Output result in another format",
@ -90,22 +63,13 @@ def _parse_cli_args():
def _init_moulinette(debug=False, quiet=False): def _init_moulinette(debug=False, quiet=False):
"""Configure logging and initialize the moulinette""" """Configure logging and initialize the moulinette"""
# Define loggers handlers
handlers = set(LOGGERS_HANDLERS)
if quiet and 'tty' in handlers:
handlers.remove('tty')
elif 'tty' not in handlers:
handlers.append('tty')
root_handlers = set(handlers) # Create log directory
if not debug and 'tty' in root_handlers: if not os.path.isdir(LOG_DIR):
root_handlers.remove('tty') try:
os.makedirs(LOG_DIR, 0750)
# Define loggers level except os.error as e:
level = LOGGERS_LEVEL _die(str(e))
tty_level = TTY_LOG_LEVEL
if debug:
tty_level = 'DEBUG'
# Custom logging configuration # Custom logging configuration
logging = { logging = {
@ -126,7 +90,7 @@ def _init_moulinette(debug=False, quiet=False):
}, },
'handlers': { 'handlers': {
'tty': { 'tty': {
'level': tty_level, 'level': 'DEBUG' if debug else 'INFO',
'class': 'moulinette.interfaces.cli.TTYHandler', 'class': 'moulinette.interfaces.cli.TTYHandler',
'formatter': 'tty-debug' if debug else '', 'formatter': 'tty-debug' if debug else '',
}, },
@ -139,45 +103,34 @@ def _init_moulinette(debug=False, quiet=False):
}, },
'loggers': { 'loggers': {
'yunohost': { 'yunohost': {
'level': level, 'level': 'DEBUG',
'handlers': handlers, 'handlers': ['file', 'tty'] if not quiet else ['file'],
'propagate': False, 'propagate': False,
}, },
'moulinette': { 'moulinette': {
'level': level, 'level': 'DEBUG',
'handlers': [], 'handlers': [],
'propagate': True, 'propagate': True,
}, },
'moulinette.interface': { 'moulinette.interface': {
'level': level, 'level': 'DEBUG',
'handlers': handlers, 'handlers': ['file', 'tty'] if not quiet else ['file'],
'propagate': False, 'propagate': False,
}, },
}, },
'root': { 'root': {
'level': level, 'level': 'DEBUG',
'handlers': root_handlers, 'handlers': ['file', 'tty'] if debug else ['file'],
}, },
} }
# Create log directory
if not os.path.isdir(LOG_DIR):
try:
os.makedirs(LOG_DIR, 0750)
except os.error as e:
_die(str(e))
# Initialize moulinette # Initialize moulinette
moulinette.init(logging_config=logging, _from_source=IN_DEVEL) moulinette.init(logging_config=logging)
def _retrieve_namespaces(): def _retrieve_namespaces():
"""Return the list of namespaces to load""" """Return the list of namespaces to load"""
ret = ['yunohost'] extensions = [n for n in ActionsMap.get_namespaces() if n.startswith('ynh_')]
for n in ActionsMap.get_namespaces(): return ['yunohost'] + extensions
# Append YunoHost modules
if n.startswith('ynh_'):
ret.append(n)
return ret
# Stupid PATH management because sometimes (e.g. some cron job) PATH is only /usr/bin:/bin ... # Stupid PATH management because sometimes (e.g. some cron job) PATH is only /usr/bin:/bin ...
default_path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" default_path = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
@ -197,10 +150,9 @@ if __name__ == '__main__':
_init_moulinette(opts.debug, opts.quiet) _init_moulinette(opts.debug, opts.quiet)
# Check that YunoHost is installed # Check that YunoHost is installed
allowed_if_not_installed = ['tools postinstall', 'backup restore', 'log display']
if not os.path.isfile('/etc/yunohost/installed') and \ if not os.path.isfile('/etc/yunohost/installed') and \
(len(args) < 2 or (args[0] +' '+ args[1] != 'tools postinstall' and \ (len(args) < 2 or (args[0] +' '+ args[1] not in allowed_if_not_installed)):
args[0] +' '+ args[1] != 'backup restore' and \
args[0] +' '+ args[1] != 'log display')):
from moulinette import m18n from moulinette import m18n
# Init i18n # Init i18n
@ -212,9 +164,11 @@ if __name__ == '__main__':
# Execute the action # Execute the action
ret = moulinette.cli( ret = moulinette.cli(
_retrieve_namespaces(), args, _retrieve_namespaces(),
use_cache=opts.use_cache, output_as=opts.output_as, args,
password=opts.password, parser_kwargs={'top_parser': parser}, output_as=opts.output_as,
password=opts.password,
timeout=opts.timeout, timeout=opts.timeout,
parser_kwargs={'top_parser': parser},
) )
sys.exit(ret) sys.exit(ret)

View file

@ -5,42 +5,18 @@ import os
import sys import sys
import argparse import argparse
# Either we are in a development environment or not import moulinette
IN_DEVEL = False from moulinette.actionsmap import ActionsMap
from moulinette.interfaces.cli import colorize
# Default server configuration # Default server configuration
DEFAULT_HOST = 'localhost' DEFAULT_HOST = 'localhost'
DEFAULT_PORT = 6787 DEFAULT_PORT = 6787
# Level for which loggers will log
LOGGERS_LEVEL = 'DEBUG'
API_LOGGER_LEVEL = 'INFO'
# Handlers that will be used by loggers
# - file: log to the file LOG_DIR/LOG_FILE
# - api: serve logs through the api
# - console: log to stderr
LOGGERS_HANDLERS = ['file', 'api']
# Directory and file to be used by logging # Directory and file to be used by logging
LOG_DIR = '/var/log/yunohost' LOG_DIR = '/var/log/yunohost'
LOG_FILE = 'yunohost-api.log' LOG_FILE = 'yunohost-api.log'
# Check and load - as needed - development environment
if not __file__.startswith('/usr/'):
IN_DEVEL = True
if IN_DEVEL:
basedir = os.path.abspath('%s/../' % os.path.dirname(__file__))
if os.path.isdir(os.path.join(basedir, 'moulinette')):
sys.path.insert(0, basedir)
LOG_DIR = os.path.join(basedir, 'log')
import moulinette
from moulinette.actionsmap import ActionsMap
from moulinette.interfaces.cli import colorize
# Initialization & helpers functions ----------------------------------- # Initialization & helpers functions -----------------------------------
def _die(message, title='Error:'): def _die(message, title='Error:'):
@ -62,46 +38,26 @@ def _parse_api_args():
action='store', default=DEFAULT_PORT, type=int, action='store', default=DEFAULT_PORT, type=int,
help="Port to listen on (default: %d)" % DEFAULT_PORT, help="Port to listen on (default: %d)" % DEFAULT_PORT,
) )
srv_group.add_argument('--no-websocket',
action='store_true', default=True, dest='use_websocket',
help="Serve without WebSocket support, used to handle "
"asynchronous responses such as the messages",
)
glob_group = parser.add_argument_group('global arguments') glob_group = parser.add_argument_group('global arguments')
glob_group.add_argument('--no-cache',
action='store_false', default=True, dest='use_cache',
help="Don't use actions map cache",
)
glob_group.add_argument('--debug', glob_group.add_argument('--debug',
action='store_true', default=False, action='store_true', default=False,
help="Set log level to DEBUG", help="Set log level to DEBUG",
) )
glob_group.add_argument('--verbose',
action='store_true', default=False,
help="Be verbose in the output",
)
glob_group.add_argument('--help', glob_group.add_argument('--help',
action='help', help="Show this help message and exit", action='help', help="Show this help message and exit",
) )
return parser.parse_args() return parser.parse_args()
def _init_moulinette(use_websocket=True, debug=False, verbose=False): def _init_moulinette(debug=False):
"""Configure logging and initialize the moulinette""" """Configure logging and initialize the moulinette"""
# Define loggers handlers
handlers = set(LOGGERS_HANDLERS)
if not use_websocket and 'api' in handlers:
handlers.remove('api')
if verbose and 'console' not in handlers:
handlers.add('console')
root_handlers = handlers - set(['api'])
# Define loggers level # Create log directory
level = LOGGERS_LEVEL if not os.path.isdir(LOG_DIR):
api_level = API_LOGGER_LEVEL try:
if debug: os.makedirs(LOG_DIR, 0750)
level = 'DEBUG' except os.error as e:
api_level = 'DEBUG' _die(str(e))
# Custom logging configuration # Custom logging configuration
logging = { logging = {
@ -122,7 +78,7 @@ def _init_moulinette(use_websocket=True, debug=False, verbose=False):
}, },
'handlers': { 'handlers': {
'api': { 'api': {
'level': api_level, 'level': 'DEBUG' if debug else 'INFO',
'class': 'moulinette.interfaces.api.APIQueueHandler', 'class': 'moulinette.interfaces.api.APIQueueHandler',
}, },
'file': { 'file': {
@ -140,58 +96,36 @@ def _init_moulinette(use_websocket=True, debug=False, verbose=False):
}, },
'loggers': { 'loggers': {
'yunohost': { 'yunohost': {
'level': level, 'level': 'DEBUG',
'handlers': handlers, 'handlers': ['file', 'api'] + ['console'] if debug else [],
'propagate': False, 'propagate': False,
}, },
'moulinette': { 'moulinette': {
'level': level, 'level': 'DEBUG',
'handlers': [], 'handlers': [],
'propagate': True, 'propagate': True,
}, },
'gnupg': {
'level': 'INFO',
'handlers': [],
'propagate': False,
},
}, },
'root': { 'root': {
'level': level, 'level': 'DEBUG',
'handlers': root_handlers, 'handlers': ['file'] + ['console'] if debug else [],
}, },
} }
# Create log directory
if not os.path.isdir(LOG_DIR):
try:
os.makedirs(LOG_DIR, 0750)
except os.error as e:
_die(str(e))
# Initialize moulinette # Initialize moulinette
moulinette.init(logging_config=logging, _from_source=IN_DEVEL) moulinette.init(logging_config=logging)
def _retrieve_namespaces(): def _retrieve_namespaces():
"""Return the list of namespaces to load""" """Return the list of namespaces to load"""
ret = ['yunohost'] extensions = [n for n in ActionsMap.get_namespaces() if n.startswith('ynh_')]
for n in ActionsMap.get_namespaces(): return ['yunohost'] + extensions
# Append YunoHost modules
if n.startswith('ynh_'):
ret.append(n)
return ret
# Callbacks for additional routes -------------------------------------- # Callbacks for additional routes --------------------------------------
def is_installed(): def is_installed():
""" """ Check whether YunoHost is installed or not """
Check whether YunoHost is installed or not return { 'installed': os.path.isfile('/etc/yunohost/installed') }
"""
installed = False
if os.path.isfile('/etc/yunohost/installed'):
installed = True
return { 'installed': installed }
# Main action ---------------------------------------------------------- # Main action ----------------------------------------------------------
@ -203,8 +137,9 @@ if __name__ == '__main__':
# Run the server # Run the server
ret = moulinette.api( ret = moulinette.api(
_retrieve_namespaces(), _retrieve_namespaces(),
host=opts.host, port=opts.port, routes={ host=opts.host,
('GET', '/installed'): is_installed, port=opts.port,
}, use_cache=opts.use_cache, use_websocket=opts.use_websocket routes={ ('GET', '/installed'): is_installed, },
use_websocket=True
) )
sys.exit(ret) sys.exit(ret)