mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
168 lines
5.3 KiB
Python
Executable file
168 lines
5.3 KiB
Python
Executable file
#! /usr/bin/python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import os
|
|
import sys
|
|
import argparse
|
|
import glob
|
|
|
|
import moulinette
|
|
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'
|
|
|
|
# Create log directory
|
|
if not os.path.isdir(LOG_DIR):
|
|
os.makedirs(LOG_DIR, 0750)
|
|
|
|
# Initialization & helpers functions -----------------------------------
|
|
|
|
|
|
def _parse_cli_args():
|
|
"""Parse additional arguments for the cli"""
|
|
parser = argparse.ArgumentParser(add_help=False)
|
|
parser.add_argument('--output-as',
|
|
choices=['json', 'plain', 'none'], default=None,
|
|
help="Output result in another format",
|
|
)
|
|
parser.add_argument('--debug',
|
|
action='store_true', default=False,
|
|
help="Log and print debug messages",
|
|
)
|
|
parser.add_argument('--quiet',
|
|
action='store_true', default=False,
|
|
help="Don't produce any output",
|
|
)
|
|
parser.add_argument('--timeout',
|
|
type=int, default=None,
|
|
help="Number of seconds before this command will timeout because it can't acquire the lock (meaning that another command is currently running), by default there is no timeout and the command will wait until it can get the lock",
|
|
)
|
|
# deprecated arguments
|
|
parser.add_argument('--plain',
|
|
action='store_true', default=False, help=argparse.SUPPRESS
|
|
)
|
|
parser.add_argument('--json',
|
|
action='store_true', default=False, help=argparse.SUPPRESS
|
|
)
|
|
|
|
opts, args = parser.parse_known_args()
|
|
|
|
# output compatibility
|
|
if opts.plain:
|
|
opts.output_as = 'plain'
|
|
elif opts.json:
|
|
opts.output_as = 'json'
|
|
|
|
return (parser, opts, args)
|
|
|
|
|
|
def _init_moulinette(debug=False, quiet=False):
|
|
"""Configure logging and initialize the moulinette"""
|
|
|
|
# Custom logging configuration
|
|
logging = {
|
|
'version': 1,
|
|
'disable_existing_loggers': True,
|
|
'formatters': {
|
|
'tty-debug': {
|
|
'format': '%(relativeCreated)-4d %(fmessage)s'
|
|
},
|
|
'precise': {
|
|
'format': '%(asctime)-15s %(levelname)-8s %(name)s %(funcName)s - %(fmessage)s'
|
|
},
|
|
},
|
|
'filters': {
|
|
'action': {
|
|
'()': 'moulinette.utils.log.ActionFilter',
|
|
},
|
|
},
|
|
'handlers': {
|
|
'tty': {
|
|
'level': 'DEBUG' if debug else 'INFO',
|
|
'class': 'moulinette.interfaces.cli.TTYHandler',
|
|
'formatter': 'tty-debug' if debug else '',
|
|
},
|
|
'file': {
|
|
'class': 'logging.FileHandler',
|
|
'formatter': 'precise',
|
|
'filename': '%s/%s' % (LOG_DIR, LOG_FILE),
|
|
'filters': ['action'],
|
|
},
|
|
},
|
|
'loggers': {
|
|
'yunohost': {
|
|
'level': 'DEBUG',
|
|
'handlers': ['file', 'tty'] if not quiet else ['file'],
|
|
'propagate': False,
|
|
},
|
|
'moulinette': {
|
|
'level': 'DEBUG',
|
|
'handlers': [],
|
|
'propagate': True,
|
|
},
|
|
'moulinette.interface': {
|
|
'level': 'DEBUG',
|
|
'handlers': ['file', 'tty'] if not quiet else ['file'],
|
|
'propagate': False,
|
|
},
|
|
},
|
|
'root': {
|
|
'level': 'DEBUG',
|
|
'handlers': ['file', 'tty'] if debug else ['file'],
|
|
},
|
|
}
|
|
|
|
# Initialize moulinette
|
|
moulinette.init(logging_config=logging)
|
|
|
|
|
|
def _retrieve_namespaces():
|
|
"""Return the list of namespaces to load"""
|
|
extensions = [n for n in ActionsMap.get_namespaces() if n.startswith('ynh_')]
|
|
return ['yunohost'] + extensions
|
|
|
|
|
|
# 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"
|
|
if os.environ["PATH"] != default_path:
|
|
os.environ["PATH"] = default_path + ":" + os.environ["PATH"]
|
|
|
|
# Main action ----------------------------------------------------------
|
|
|
|
if __name__ == '__main__':
|
|
if os.geteuid() != 0:
|
|
# since moulinette isn't initialized, we can't use m18n here
|
|
sys.stderr.write("\033[1;31mError:\033[0m yunohost command must be "
|
|
"run as root or with sudo.\n")
|
|
sys.exit(1)
|
|
|
|
parser, opts, args = _parse_cli_args()
|
|
_init_moulinette(opts.debug, opts.quiet)
|
|
|
|
# Check that YunoHost is installed
|
|
allowed_if_not_installed = ['tools postinstall', 'backup restore', 'log display']
|
|
if not os.path.isfile('/etc/yunohost/installed') and \
|
|
(len(args) < 2 or (args[0] + ' ' + args[1] not in allowed_if_not_installed)):
|
|
|
|
from moulinette import m18n
|
|
# Init i18n
|
|
m18n.load_namespace('yunohost')
|
|
m18n.set_locale(get_locale())
|
|
|
|
# Print error and exit
|
|
print(colorize(m18n.g('error'), 'red') + " " + m18n.n('yunohost_not_installed'))
|
|
sys.exit(1)
|
|
|
|
extensions = [f.split('/')[-1][:-4] for f in glob.glob("/usr/share/moulinette/actionsmap/ynh_*.yml")]
|
|
|
|
# Execute the action
|
|
ret = moulinette.cli(
|
|
['yunohost'] + extensions,
|
|
args,
|
|
output_as=opts.output_as,
|
|
timeout=opts.timeout,
|
|
parser_kwargs={'top_parser': parser},
|
|
)
|
|
sys.exit(ret)
|