Browse Source

update: colorful debug output

pull/2/head
Dnomd343 1 year ago
parent
commit
b5d42e0019
  1. 51
      boot.py

51
boot.py

@ -1,8 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# from __future__ import annotations
import os import os
import sys import sys
import yaml import yaml
@ -14,10 +12,17 @@ from syncplay import ep_server
class SyncplayBoot: class SyncplayBoot:
""" Handle Syncplay bootstrap arguments. """ """ Handle Syncplay bootstrap arguments. """
def __debug(self, msg: str) -> None: def __debug(self, prefix: str, message: Any) -> None:
""" Print out debug information. """ """ Print out debug information. """
if self.__debug_mode: if self.__debug_mode:
print(f'\033[90m{msg}\033[0m', file=sys.stderr) print(f'\033[33m{prefix}\033[0m -> \033[90m{message}\033[0m', file=sys.stderr)
def __temp_file(self, file: str, content: str) -> str:
""" Create and save content to temporary files. """
file = os.path.join(self.__temp_dir, file)
with open(file, 'w', encoding='utf-8') as fp:
fp.write(content)
return file
def __build_parser(self) -> Generator: def __build_parser(self) -> Generator:
""" Build arguments parser for Syncplay bootstrap. """ """ Build arguments parser for Syncplay bootstrap. """
@ -48,33 +53,32 @@ class SyncplayBoot:
yield action.dest, opt_type, is_list yield action.dest, opt_type, is_list
def __init__(self, args: list[str], config: dict[str, Any], def __init__(self, args: list[str], config: dict[str, Any],
work_dir: str, cert_dir: str, debug_mode: bool = False): cert_dir: str, temp_dir: str, work_dir: str, debug_mode: bool = False):
self.__work_dir = work_dir
self.__cert_dir = cert_dir
self.__debug_mode = debug_mode self.__debug_mode = debug_mode
self.__cert_dir, self.__temp_dir, self.__work_dir = cert_dir, temp_dir, work_dir
self.__options = [x for x in self.__build_options()] # list[(NAME, TYPE, IS_LIST)] self.__options = [x for x in self.__build_options()] # list[(NAME, TYPE, IS_LIST)]
self.__debug(f'Bootstrap options -> {self.__options}\n') self.__debug('Bootstrap options', self.__options)
env_opts = self.__load_from_env() env_opts = self.__load_from_env()
self.__debug(f'Environment options -> {env_opts}\n') self.__debug('Environment options', env_opts)
cfg_opts = self.__load_from_config(config) cfg_opts = self.__load_from_config(config)
self.__debug(f'Configure file options -> {cfg_opts}\n') self.__debug('Configure file options', cfg_opts)
cli_opts = self.__load_from_args(args) cli_opts = self.__load_from_args(args)
self.__debug(f'Command line options -> {cli_opts}\n') self.__debug('Command line options', cli_opts)
self.__opts = env_opts | cfg_opts | cli_opts self.__opts = env_opts | cfg_opts | cli_opts
self.__debug(f'Bootstrap final options -> {self.__opts}\n') self.__debug('Bootstrap final options', self.__opts)
def __load_from_args(self, raw_args: list[str]) -> dict[str, Any]: def __load_from_args(self, raw_args: list[str]) -> dict[str, Any]:
""" Loading options from command line arguments. """ """ Loading options from command line arguments. """
args = self.__parser.parse_args(raw_args) args = self.__parser.parse_args(raw_args)
self.__debug(f'Command line arguments -> {args}') self.__debug('Command line arguments', args)
arg_filter = lambda x: x is not None and x is not False arg_filter = lambda x: x is not None and x is not False
return {x: y for x, y in vars(args).items() if arg_filter(y)} return {x: y for x, y in vars(args).items() if arg_filter(y)}
def __load_from_config(self, config: dict[str, Any]) -> dict[str, Any]: def __load_from_config(self, config: dict[str, Any]) -> dict[str, Any]:
""" Loading options from configure file. """ """ Loading options from configure file. """
self.__debug(f'Configure file -> {config}') self.__debug('Configure file', config)
options = {x[0].replace('_', '-'): x[0] for x in self.__options} options = {x[0].replace('_', '-'): x[0] for x in self.__options}
return {options[x]: config[x] for x in options if x in config} return {options[x]: config[x] for x in options if x in config}
@ -88,25 +92,17 @@ class SyncplayBoot:
elif opt_type is bool: elif opt_type is bool:
return opt_field, opt_raw.upper() in ['ON', 'TRUE'] return opt_field, opt_raw.upper() in ['ON', 'TRUE']
self.__debug(f'Environment variables -> {os.environ}') self.__debug('Environment variables', os.environ)
options = {x.upper(): (x, t) for x, t, is_list in self.__options if not is_list} # filter non-list options options = {x.upper(): (x, t) for x, t, is_list in self.__options if not is_list} # filter non-list options
return dict([__convert(os.environ[x], *y) for x, y in options.items() if x in os.environ]) return dict([__convert(os.environ[x], *y) for x, y in options.items() if x in os.environ])
@staticmethod
def __temp_file(file: str, content: str) -> str:
""" Create and save content to temporary files. """
file = os.path.join('/tmp/', file)
with open(file, 'w') as fp:
fp.write(content)
return file
def release(self) -> list[str]: def release(self) -> list[str]:
""" Construct the startup arguments for syncplay server. """ """ Construct the startup arguments for syncplay server. """
args = ['--port', str(self.__opts.get('port', 8999))] args = ['--port', str(self.__opts.get('port', 8999))]
if 'password' in self.__opts: if 'password' in self.__opts:
args += ['--password', self.__opts['password']] args += ['--password', self.__opts['password']]
if 'motd' in self.__opts: if 'motd' in self.__opts:
args += ['--motd-file', SyncplayBoot.__temp_file('motd.data', self.__opts['motd'])] args += ['--motd-file', self.__temp_file('motd.data', self.__opts['motd'])]
salt = self.__opts.get('salt', None if 'random_salt' in self.__opts else '') salt = self.__opts.get('salt', None if 'random_salt' in self.__opts else '')
if salt is not None: if salt is not None:
@ -128,7 +124,7 @@ class SyncplayBoot:
args += ['--max-chat-message-length', str(self.__opts['max_chat_message'])] args += ['--max-chat-message-length', str(self.__opts['max_chat_message'])]
if 'permanent_rooms' in self.__opts: if 'permanent_rooms' in self.__opts:
rooms = '\n'.join(self.__opts['permanent_rooms']) rooms = '\n'.join(self.__opts['permanent_rooms'])
args += ['--permanent-rooms-file', SyncplayBoot.__temp_file('rooms.list', rooms)] args += ['--permanent-rooms-file', self.__temp_file('rooms.list', rooms)]
if 'listen_ipv4' in self.__opts and 'listen_ipv6' in self.__opts: if 'listen_ipv4' in self.__opts and 'listen_ipv6' in self.__opts:
args += ['--interface-ipv4', self.__opts['listen_ipv4']] args += ['--interface-ipv4', self.__opts['listen_ipv4']]
@ -138,19 +134,20 @@ class SyncplayBoot:
elif 'listen_ipv6' in self.__opts: elif 'listen_ipv6' in self.__opts:
args += ['--ipv6-only', '--interface-ipv6', self.__opts['listen_ipv6']] args += ['--ipv6-only', '--interface-ipv6', self.__opts['listen_ipv6']]
self.__debug(f'Syncplay startup arguments -> {args}') self.__debug('Syncplay startup arguments', args)
return args return args
def syncplay_boot() -> None: def syncplay_boot() -> None:
""" Bootstrap the syncplay server. """ """ Bootstrap the syncplay server. """
temp_dir = os.environ.get('TEMP_DIR', '/tmp')
work_dir = os.environ.get('WORK_DIR', '/data') work_dir = os.environ.get('WORK_DIR', '/data')
cert_dir = os.environ.get('CERT_DIR', '/certs') cert_dir = os.environ.get('CERT_DIR', '/certs')
config_file = os.environ.get('CONFIG', 'config.yml') config_file = os.environ.get('CONFIG', 'config.yml')
debug_mode = os.environ.get('DEBUG', '').upper() in ['ON', 'TRUE'] debug_mode = os.environ.get('DEBUG', '').upper() in ['ON', 'TRUE']
config = yaml.safe_load(open(config_file).read()) if os.path.exists(config_file) else {} config = yaml.safe_load(open(config_file).read()) if os.path.exists(config_file) else {}
bootstrap = SyncplayBoot(sys.argv[1:], config, work_dir, cert_dir, debug_mode) bootstrap = SyncplayBoot(sys.argv[1:], config, cert_dir, temp_dir, work_dir, debug_mode)
sys.argv = ['syncplay'] + bootstrap.release() sys.argv = ['syncplay'] + bootstrap.release()

Loading…
Cancel
Save