[enh] Refactor bin/yunohost-api to follow moulinette changes and add help

This commit is contained in:
Jérôme Lebleu 2015-11-13 21:46:54 +01:00
parent fe6a01f206
commit 0a78238041

View file

@ -7,24 +7,32 @@ import os.path
# Either we are in a development environment or not # Either we are in a development environment or not
IN_DEVEL = False IN_DEVEL = False
# Either cache has to be used inside the moulinette or not # Default server configuration
USE_CACHE = True DEFAULT_HOST = 'localhost'
DEFAULT_PORT = 6787
# Either WebSocket has to be installed by the moulinette or not
USE_WEBSOCKET = True
# Level for which loggers will log # Level for which loggers will log
LOGGERS_LEVEL = 'INFO' LOGGERS_LEVEL = 'INFO'
# Handlers that will be used by loggers # Handlers that will be used by loggers
# - file: log to the file LOG_DIR/LOG_FILE # - file: log to the file LOG_DIR/LOG_FILE
# - api: serve logs through the api
# - console: log to stderr # - console: log to stderr
LOGGERS_HANDLERS = ['file'] 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')
# Initialization & helpers functions ----------------------------------- # Initialization & helpers functions -----------------------------------
@ -37,80 +45,113 @@ def _die(message, title='Error:'):
print('%s %s' % (colorize(title, 'red'), message)) print('%s %s' % (colorize(title, 'red'), message))
sys.exit(1) sys.exit(1)
def _check_in_devel(): def _parse_api_args():
"""Check and load if needed development environment""" """Parse main arguments for the api"""
global IN_DEVEL, LOG_DIR import argparse
basedir = os.path.abspath('%s/../' % os.path.dirname(__file__))
if os.path.isdir('%s/moulinette' % basedir) and not IN_DEVEL:
# Add base directory to python path
sys.path.insert(0, basedir)
# Update global variables parser = argparse.ArgumentParser(add_help=False,
IN_DEVEL = True description="Run the YunoHost API to manage your server.",
LOG_DIR = '%s/log' % basedir )
srv_group = parser.add_argument_group('server configuration')
srv_group.add_argument('-h', '--host',
action='store', default=DEFAULT_HOST,
help="Host to listen on (default: %s)" % DEFAULT_HOST,
)
srv_group.add_argument('-p', '--port',
action='store', default=DEFAULT_PORT, type=int,
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.add_argument('--no-cache',
action='store_false', default=True, dest='use_cache',
help="Don't use actions map cache",
)
glob_group.add_argument('--debug',
action='store_true', default=False,
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',
action='help', help="Show this help message and exit",
)
def _parse_argv(): return parser.parse_args()
"""Parse additional arguments and return remaining ones"""
argv = list(sys.argv)
argv.pop(0)
if '--no-cache' in argv: def _init_moulinette(use_websocket=True, debug=False, verbose=False):
global USE_CACHE
USE_CACHE = False
argv.remove('--no-cache')
if '--no-websocket' in argv:
global USE_WEBSOCKET
USE_WEBSOCKET = False
argv.remove('--no-websocket')
if '--debug' in argv:
global LOGGERS_LEVEL
LOGGERS_LEVEL = 'DEBUG'
argv.remove('--debug')
if '--verbose' in argv:
global LOGGERS_HANDLERS
if 'console' not in LOGGERS_HANDLERS:
LOGGERS_HANDLERS.append('console')
argv.remove('--verbose')
return argv
def _init_moulinette():
"""Configure logging and initialize the moulinette""" """Configure logging and initialize the moulinette"""
from moulinette import init from moulinette import init
# 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
level = LOGGERS_LEVEL
if debug:
level = 'DEBUG'
# Custom logging configuration # Custom logging configuration
logging = { logging = {
'version': 1, 'version': 1,
'disable_existing_loggers': True, 'disable_existing_loggers': True,
'formatters': { 'formatters': {
'simple': { 'console': {
'format': '%(relativeCreated)-5d %(levelname)-8s %(name)s - %(message)s' 'format': '%(relativeCreated)-5d %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
}, },
'precise': { 'precise': {
'format': '%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(message)s' 'format': '%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
},
},
'filters': {
'action': {
'()': 'moulinette.utils.log.ActionFilter',
}, },
}, },
'handlers': { 'handlers': {
'console': { 'api': {
'class': 'logging.StreamHandler', 'class': 'moulinette.interfaces.api.APIQueueHandler',
'formatter': 'simple',
'stream': 'ext://sys.stderr',
}, },
'file': { 'file': {
'class': 'logging.handlers.WatchedFileHandler', 'class': 'logging.handlers.WatchedFileHandler',
'formatter': 'precise', 'formatter': 'precise',
'filename': '%s/%s' % (LOG_DIR, LOG_FILE), 'filename': '%s/%s' % (LOG_DIR, LOG_FILE),
'filters': ['action'],
},
'console': {
'class': 'logging.StreamHandler',
'formatter': 'console',
'stream': 'ext://sys.stdout',
'filters': ['action'],
}, },
}, },
'loggers': { 'loggers': {
'moulinette': { 'moulinette': {
'level': LOGGERS_LEVEL, 'level': level,
'handlers': LOGGERS_HANDLERS, 'handlers': handlers,
'propagate': False,
}, },
'yunohost': { 'yunohost': {
'level': LOGGERS_LEVEL, 'level': level,
'handlers': LOGGERS_HANDLERS, 'handlers': handlers,
'propagate': False,
}, },
}, },
'root': {
'level': level,
'handlers': root_handlers,
},
} }
# Create log directory # Create log directory
@ -150,20 +191,18 @@ def is_installed():
# Main action ---------------------------------------------------------- # Main action ----------------------------------------------------------
if __name__ == '__main__': if __name__ == '__main__':
_check_in_devel() opts = _parse_api_args()
_parse_argv() _init_moulinette(opts.use_websocket, opts.debug, opts.verbose)
_init_moulinette()
from moulinette import (api, MoulinetteError)
from yunohost import get_versions
try:
# Run the server # Run the server
api(_retrieve_namespaces(), port=6787, from moulinette import api, MoulinetteError
from yunohost import get_versions
ret = api(_retrieve_namespaces(),
host=opts.host, port=opts.port,
routes={ routes={
('GET', '/installed'): is_installed, ('GET', '/installed'): is_installed,
('GET', '/version'): get_versions, ('GET', '/version'): get_versions,
}, },
use_cache=USE_CACHE, use_websocket=USE_WEBSOCKET) use_cache=opts.use_cache, use_websocket=opts.use_websocket
except MoulinetteError as e: )
_die(e.strerror, m18n.g('error')) sys.exit(ret)
sys.exit(0)