From ef7656ddea7278fa68ec1758745215cee929fac7 Mon Sep 17 00:00:00 2001 From: jpic Date: Sat, 18 Apr 2020 17:33:49 +0200 Subject: [PATCH] wip --- shlax/actions/base.py | 19 +++++++--- shlax/actions/packages.py | 4 +-- shlax/actions/run.py | 16 ++++++--- shlax/cli.py | 75 ++++++++++++++++++++++++++++++++++----- shlax/exceptions.py | 4 +-- shlax/proc.py | 5 ++- 6 files changed, 99 insertions(+), 24 deletions(-) diff --git a/shlax/actions/base.py b/shlax/actions/base.py index 51b2ad8..fffd955 100644 --- a/shlax/actions/base.py +++ b/shlax/actions/base.py @@ -9,11 +9,10 @@ from ..exceptions import WrongResult from ..result import Result - - class class_or_instance_method: def __init__(self, f): self.f = f + def __get__(self, instance, owner): def newfunc(*args, **kwargs): return self.f( @@ -43,10 +42,16 @@ class Action: '''.strip(), immediate=True, ), + v=dict( + default=False, + help='Verbose, like -d=visit,cmd,out', + immediate=True, + ), ) def __init__(self, *args, **kwargs): self.args = args + self.kwargs = kwargs for key, value in kwargs.items(): setattr(self, key, value) if isinstance(value, Action): @@ -110,7 +115,10 @@ class Action: from ..targets.localhost import Localhost targets = [Localhost()] - output = Output(regexp=self.regexps, debug=True) + output = Output( + regexp=self.regexps, + debug='cmd,visit,out' if options['v'] else options['debug'], + ) results = [] for target in targets: target.output = output @@ -130,7 +138,10 @@ class Action: action.step = step output.start(action) try: - await getattr(action, step)() + if isinstance(getattr(action, step), Action): + await getattr(action, step)(**options) + else: + await getattr(action, step)() except Exception as e: output.fail(action, e) action.result.status = 'fail' diff --git a/shlax/actions/packages.py b/shlax/actions/packages.py index a7ff83c..48e1638 100644 --- a/shlax/actions/packages.py +++ b/shlax/actions/packages.py @@ -94,7 +94,7 @@ class Packages(Action): f.write(str(os.getpid())) try: - await self.rexec(self.cmds['update']) + await self.target.rexec(self.cmds['update']) finally: os.unlink(lockfile) @@ -102,7 +102,7 @@ class Packages(Action): f.write(str(now)) else: while os.path.exists(lockfile): - print(f'{self.container.name} | Waiting for update ...') + print(f'{self.target} | Waiting for {lockfile} ...') await asyncio.sleep(1) async def apply(self): diff --git a/shlax/actions/run.py b/shlax/actions/run.py index e30f252..e392d42 100644 --- a/shlax/actions/run.py +++ b/shlax/actions/run.py @@ -3,14 +3,20 @@ from .base import Action class Run(Action): """Run a script or command on a target.""" - async def call(self, *args, **kwargs): - image = self.kwargs.get('image', None) - if not image: - return await self.exec(*self.args, **self.kwargs) + def __init__(self, *args, image=None, **kwargs): + super().__init__(**kwargs) + self.args = args + self.kwargs = kwargs + self.image = image + + async def apply(self): + if not self.image: + return await self.target.exec(*self.args, **self.kwargs) + from ..targets.buildah import Buildah from ..targets.docker import Docker + if isinstance(image, Buildah): - breakpoint() result = await self.action(image, *args, **kwargs) return await Docker( diff --git a/shlax/cli.py b/shlax/cli.py index b8080db..b153d8a 100644 --- a/shlax/cli.py +++ b/shlax/cli.py @@ -46,20 +46,53 @@ class ConsoleScript(cli2.ConsoleScript): super().append(arg) def __call__(self): - if len(sys.argv) > 1 and os.path.exists(sys.argv[1]): - pass + if len(self.argv) > 1 and os.path.exists(self.argv[1]): + self.argv = sys.argv[1:] + + spec = importlib.util.spec_from_file_location('shlaxfile', sys.argv[1]) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + self.doc = (inspect.getdoc(mod) or '').split("\n")[0] + for name, value in mod.__dict__.items(): + if isinstance(value, Action): + self[name] = cli2.Callable( + name, + self.action(value), + doc=type(value).__doc__, + options={ + option: cli2.Option(option, **cfg) + for option, cfg in value.options.items() + } + ) + #self[name] = value + #elif callable(value) and getattr(value, '__name__', '').startswith('test_'): + # self.tests[value.__name__] = value + + #modname = sys.argv[1].split('/')[-1].replace('.py', '') + #mod = importlib.import_module('shlax.actions.' + modname) else: scripts = glob.glob(os.path.join( os.path.dirname(__file__), 'actions', '*.py')) for script in scripts: modname = script.split('/')[-1].replace('.py', '') + if modname == '__init__': + continue + mod = importlib.import_module('shlax.actions.' + modname) for key, value in mod.__dict__.items(): + if key == '__builtins__': + continue if key.lower() != modname: continue break self[modname] = cli2.Callable( - modname, self.action_class(value)) + modname, + self.action_class(value), + options={ + option: cli2.Option(option, **cfg) + for option, cfg in value.options.items() + } + ) scripts = glob.glob(os.path.join( os.path.dirname(__file__), 'repo', '*.py')) @@ -74,22 +107,48 @@ class ConsoleScript(cli2.ConsoleScript): if key == 'main': if len(value.steps()) == 1: self[modname] = cli2.Callable( - modname, self.action(value), doc=doc) + modname, + self.action(value), + doc=doc, + options={ + option: cli2.Option(option, **cfg) + for option, cfg in value.options.items() + } + ) else: for name, method in value.steps().items(): self[modname][name] = cli2.Callable( - modname, self.action(value), - doc=inspect.getdoc(method) + modname, + self.action(value), + doc=inspect.getdoc(method), + options={ + option: cli2.Option(option, **cfg) + for option, cfg in value.options.items() + } ) else: if len(value.steps()) == 1: self[modname][key] = cli2.Callable( - modname, self.action(value), doc=doc) + modname, + self.action(value), + doc=doc, + options={ + option: cli2.Option(option, **cfg) + for option, cfg in value.options.items() + } + ) else: self[modname][key] = cli2.Group('steps') for step in value.steps(): self[modname][key][step] = cli2.Callable( - modname, self.action(value), doc='lol') + modname, + self.action(value), + doc='lol', + options={ + option: cli2.Option(option, **cfg) + for option, cfg in value.options.items() + } + ) return super().__call__() diff --git a/shlax/exceptions.py b/shlax/exceptions.py index 0d5e9f4..5b161a9 100644 --- a/shlax/exceptions.py +++ b/shlax/exceptions.py @@ -12,10 +12,10 @@ class WrongResult(ShlaxException): msg = f'FAIL exit with {proc.rc} ' + proc.args[0] - if not proc.debug or 'cmd' not in str(proc.debug): + if not proc.output.debug or 'cmd' not in str(proc.output.debug): msg += '\n' + proc.cmd - if not proc.debug or 'out' not in str(proc.debug): + if not proc.output.debug or 'out' not in str(proc.output.debug): msg += '\n' + proc.out msg += '\n' + proc.err diff --git a/shlax/proc.py b/shlax/proc.py index d50c0f8..38c9afc 100644 --- a/shlax/proc.py +++ b/shlax/proc.py @@ -54,8 +54,7 @@ class Proc: """ test = False - def __init__(self, *args, prefix=None, raises=True, debug=None, output=None): - self.debug = debug if not self.test else False + def __init__(self, *args, prefix=None, raises=True, output=None): self.output = output or Output() self.cmd = ' '.join(args) self.args = args @@ -87,7 +86,7 @@ class Proc: if self.called: raise Exception('Already called: ' + self.cmd) - if self.debug is True or 'cmd' in str(self.debug): + if 'cmd' in str(self.output.debug): self.output.cmd(self.cmd) if self.test: