diff --git a/__init__.py b/__init__.py index 325af77..607bc8b 100644 --- a/__init__.py +++ b/__init__.py @@ -76,7 +76,7 @@ def run(group, arglist): if pos >= SERVICE: unorder = True pos = SERVICE - elif arg in serv.info or arg == 'all': + elif arg in serv.info or arg == 'all' or serv.wildcard(arg) is not None: args['ins'] = arg if pos >= INS: unorder = True diff --git a/base.py b/base.py index f64ccd1..e0341ce 100644 --- a/base.py +++ b/base.py @@ -202,6 +202,15 @@ class ServiceManager: result.setdefault(ins, {}).setdefault(serv, []).append(p) return result + def wildcard(self, ins): + if ins is None or ins == 'all': + return list(self.info) + pat = re.sub(r'(\.|\*)', '.*', ins) + if pat == ins: + return None + pat = re.compile(pat) + return [k for k in self.info if pat.match(k)] + def check_running(self, ins, service): self.get_info() if ins not in self.info: @@ -215,6 +224,9 @@ class ServiceManager: def stop(self, ins, service=None): """stop service (or all services) of instance """ + ins_list = self.wildcard(ins) + if ins_list is not None: + return ins_list procs = self.get_procs() done = False services = self.services if service is None else [service] @@ -247,6 +259,9 @@ class ServiceManager: def do_stop(self, ins, service=None, *args): self.get_info() + ins_list = self.wildcard(ins) + if ins_list is not None: + return ins_list if not self.stop(ins, service): print('nothing to stop') @@ -258,6 +273,9 @@ class ServiceManager: return env.get('%s_ROOT' % gr, ''), env def do_start(self, ins, service=None, cfg='', restart=False, wait=False, logger=None): + ins_list = self.wildcard(ins) + if ins_list is not None: + return ins_list if logger is None: class logger: @staticmethod @@ -349,10 +367,15 @@ class ServiceManager: os.chdir(wd) def do_restart(self, ins, service=None, cfg=None, logger=None): + ins_list = self.wildcard(ins) + if ins_list is not None: + return ins_list self.do_start(ins, service, cfg, True, logger=logger) def do_run(self, ins, service=None, cfg=None): """for tests: run and wait""" + if self.wildcard(ins) is not None: + raise UsageError('no wildcards allowed with %s run' % self.group) if not service: try: service, = self.services @@ -362,17 +385,22 @@ class ServiceManager: def do_list(self, ins=None, *args): """info about running services""" + show_unused = ins == 'all' + if show_unused: + ins = None + instances = self.wildcard(ins) + if instances is None: + ins_set = {ins} + else: + ins_set = set(instances) cfginfo = {} procs = self.get_procs(self.all, cfginfo) rows = [] merged = OrderedDict() - show_unused = ins == 'all' - if show_unused: - ins = None for group, sm in self.all.items(): sm.get_info() for ins_i, info_dict in sm.info.items(): - if ins is not None and ins != ins_i: + if ins_i not in ins_set: continue for serv, port in info_dict.items(): if ins_i not in merged: @@ -417,18 +445,25 @@ class ServiceManager: if not callable(method): raise UsageError('%s is no valid action' % action) try: - method(*args) + ins_list = method(*args) except TypeError as e: errtxt = str(e) if 'do_%s(' % action in errtxt and 'argument' in errtxt: raise UsageError(errtxt) raise + # treat wildcards: + for ins in ins_list or (): + print('\n%s %s %s:' % (action, self.group, ins)) + try: + method(ins, *args[1:]) + except Exception as e: + print(str(e)) def do_help(self, *args): if self.main_ins: usage = self.USAGE.replace(' ', '').replace(' []', '') % '' else: - usage = self.USAGE % (' is one of %s' % ', '.join(self.info)) + usage = self.USAGE % (' is one of %s' % ', '.join(self.info)) print(usage) def treat_args(self, argdict, unknown=(), extra=()): diff --git a/frappyman.py b/frappyman.py index 98025c5..eb92393 100644 --- a/frappyman.py +++ b/frappyman.py @@ -34,14 +34,15 @@ class FrappyManager(ServiceManager): USAGE = """ Usage: - frappy list [] + frappy list [] * frappy start - frappy restart [] [] - frappy stop [] + frappy restart [] [] * + frappy stop [] * frappy listcfg [] # list available cfg files is one of main, stick, addons %s + * wildcards allowed, using '.' to replace 0 or more arbitrary characters in """ def config_dirs(self, ins, service): @@ -70,6 +71,8 @@ class FrappyManager(ServiceManager): return start_dir, env def do_start(self, ins, service=None, cfg='', restart=False, wait=False, logger=None): + if self.wildcard(ins) is not None: + raise UsageError('no wildcards allowed with %s start' % self.group) if cfg and not service and len(self.services) != 1: raise UsageError('need service to start (one of %s)' % ', '.join(self.services)) super().do_start(ins, service, cfg, restart, wait, logger) diff --git a/nicosman.py b/nicosman.py index 2f65d6e..78cc459 100644 --- a/nicosman.py +++ b/nicosman.py @@ -26,7 +26,7 @@ import shutil from glob import glob from os.path import join, abspath, dirname, basename, expanduser, exists, islink from configparser import ConfigParser -from servicemanager.base import ServiceManager +from servicemanager.base import ServiceManager, UsageError ENV_KEYS = { @@ -56,16 +56,16 @@ class NicosManager(ServiceManager): nicos gui nicos (the same as above) - nicos list [] - nicos start [] - nicos restart [] - nicos stop [] - nicos create - nicos create all + nicos list [] * + nicos start [] * + nicos restart [] * + nicos stop [] * + nicos create * nicos link (create links to nicos data and scripts) is one of main, stick, addons %s + * wildcards allowed, using '.' to replace 0 or more arbitrary characters in to be done after the experiment: nicos copy (copy data and scripts from link) @@ -87,12 +87,14 @@ class NicosManager(ServiceManager): env['NICOS_PACKAGE'] = basename(dirname(instdir[0])) def do_create(self, ins, *args): - self.get_info() - if ins == 'all' or ins == 'check': - inslist = list(self.info) + if ins == 'check': + ins_list = self.wildcard(None) else: - inslist = [ins] - for ins_i in inslist: + ins_list = self.wildcard(ins) + if ins_list is None: + ins_list = [ins] + self.get_info() + for ins_i in ins_list: env = self.env[ins_i] base = join(env['NICOS_ROOT'], env['NICOS_PACKAGE'], ins) nicos_conf = join(base, 'nicos.conf') @@ -238,6 +240,8 @@ class NicosManager(ServiceManager): return start_dir, env def prepare_client(self, ins): + if self.wildcard(ins): + raise UsageError('wildcards not allowed') self.check_running(ins, 'daemon') env = self.prepare_start(ins, 'daemon')[1] os.environ.update(env) diff --git a/seaman.py b/seaman.py index d158496..b96b01c 100644 --- a/seaman.py +++ b/seaman.py @@ -52,15 +52,16 @@ class SeaManager(ServiceManager): Usage: sea gui - sea # the same as sea gui - sea cli # the same as old seacmd - sea start [] # the same as old 'monit start sea' - sea restart [] - sea stop [] - sea list [] + sea # the same as sea gui + sea cli # the same as old seacmd + sea start [] * # the same as old 'monit start sea' + sea restart [] * + sea stop [] * + sea list [] * is one of sea, graph %s + * wildcards allowed, using '.' to replace 0 or more arbitrary characters in """ def do_cli(self, ins):