11from .
import control, shell, utils
13DEFAULT_SERVICE_PLUGINS = [
14 'testsuite.databases.mongo.pytest_plugin',
15 'testsuite.databases.pgsql.pytest_plugin',
16 'testsuite.databases.redis.pytest_plugin',
17 'testsuite.databases.mysql.pytest_plugin',
18 'testsuite.databases.clickhouse.pytest_plugin',
19 'testsuite.databases.rabbitmq.pytest_plugin',
20 'testsuite.databases.kafka.pytest_plugin',
23logger = logging.getLogger(__name__)
28 logging.DEBUG: colors.Colors.GRAY,
29 logging.INFO: colors.Colors.BRIGHT_GREEN,
30 logging.WARNING: colors.Colors.YELLOW,
31 logging.ERROR: colors.Colors.RED,
32 logging.CRITICAL: colors.Colors.BRIGHT_RED,
35 def __init__(self, *, colors_enabled=False):
39 def format(self, record: logging.LogRecord):
40 message = super().format(record)
42 return f
'{record.levelname} {message}'
43 color = self.
LEVEL_COLORS.get(record.levelno, colors.Colors.DEFAULT)
44 return f
'{color}{record.levelname}{colors.Colors.DEFAULT} {message}'
47def csv_arg(value: str):
49 for arg
in value.split(
','):
56def main(args=None, service_plugins=None):
57 utils.ensure_non_root_user()
58 testsuite_services = _register_services(service_plugins)
59 default_services = sorted(testsuite_services.keys())
61 parser = argparse.ArgumentParser()
64 help=
'Path environment data directry.',
72 help=
'Force run, ignore failures',
77 help=
'Do not re-raise already running services',
79 services_group = parser.add_mutually_exclusive_group()
80 services_group.add_argument(
85 help=
'Comma separated list of services (default: %(default)s)',
86 default=default_services,
88 services_group.add_argument(
91 help=
'Deprecated! List of services (default: %(default)s)',
92 default=default_services,
96 choices=[
'debug',
'info',
'warning',
'error',
'critical'],
99 parser.set_defaults(handler=
None)
101 subparsers = parser.add_subparsers(metavar=
'command')
103 command_parser = subparsers.add_parser(
'start', help=
'Start services')
104 command_parser.set_defaults(handler=_command_start)
106 command_parser = subparsers.add_parser(
'stop', help=
'Stop services')
107 command_parser.set_defaults(handler=_command_stop)
109 command_parser = subparsers.add_parser(
111 help=
'Run command with services started',
113 command_parser.add_argument(
'command', nargs=
'+', help=
'Command to run')
114 command_parser.set_defaults(handler=_command_run)
116 args = parser.parse_args(args=args)
117 if args.handler
is None:
118 parser.error(
'the following arguments are required: command')
120 _setup_logging(args.log_level.upper())
122 config = control.load_environment_config(
123 env_dir=args.env_dir,
124 reuse_services=args.reuse_services,
128 for service_name, service_class
in testsuite_services.items():
129 env.register_service(service_name, service_class)
130 args.handler(env, args)
133def _setup_logging(log_level):
134 root_logger = logging.getLogger()
135 root_logger.setLevel(log_level)
136 handler = logging.StreamHandler(sys.stderr)
137 handler.setFormatter(
139 colors_enabled=sys.stderr.isatty(),
142 root_logger.addHandler(handler)
145def _command_start(env, args):
147 for service_name
in args.services:
149 env.ensure_started(service_name)
152 'Failed to start service %s: %s',
163def _command_stop(env, args):
165 for service_name
in args.services:
167 env.stop_service(service_name)
170 'Failed to stop service %s: %s',
181def _command_run(env, args):
182 _command_start(env, args)
183 with contextlib.closing(env):
184 exit_code = subprocess.call(args.command)
188def _register_services(service_plugins=None):
191 def _register_service(name, factory=None):
192 def decorator(factory):
193 services[name] = factory
197 return decorator(factory)
199 if service_plugins
is None:
200 service_plugins = DEFAULT_SERVICE_PLUGINS
205 for modname
in service_plugins:
207 mod = importlib.import_module(modname)
212 mod.pytest_service_register(register_service=_register_service)
216if __name__ ==
'__main__':