yunohost/bin/yunohost
2020-05-07 22:15:51 +02:00

164 lines
5.2 KiB
Python
Executable file

#! /usr/bin/python
# -*- coding: utf-8 -*-
import os
import sys
import argparse
import glob
import moulinette
# Directory and file to be used by logging
LOG_DIR = '/var/log/yunohost'
LOG_FILE = 'yunohost-cli.log'
# 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(debug=False, quiet=False, logfile='%s/%s' % (LOG_DIR, LOG_FILE)):
logdir = os.path.dirname(logfile)
if not os.path.isdir(logdir):
os.makedirs(logdir, 0750)
moulinette.init(logging_config={
'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': logfile,
'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'],
},
})
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(debug=opts.debug, quiet=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
from moulinette.interfaces.cli import colorize, get_locale
# 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)