diff --git a/shlax/actions/base.py b/shlax/actions/base.py index f8b63bc..c1d36c6 100644 --- a/shlax/actions/base.py +++ b/shlax/actions/base.py @@ -85,7 +85,7 @@ class Action: for a in self.parents() + self.sibblings() + self.children(): if name in a.contextualize: return getattr(a, name) - raise AttributeError(name) + raise AttributeError(f'{type(self).__name__} has no {name}') async def call(self, *args, **kwargs): print(f'{self}.call(*args, **kwargs) not implemented') @@ -101,23 +101,34 @@ class Action: self.status = 'running' try: result = await self.call(*args, **kwargs) - except WrongResult as e: + except Exception as e: self.output_fail(e) self.status = 'fail' - result = e.proc.rc + proc = getattr(e, 'proc', None) + result = proc.rc if proc else 1 else: self.output_success() if self.status == 'running': self.status = 'success' + finally: + clean = getattr(self, 'clean', None) + if clean: + await clean(*args, **kwargs) return result def output_start(self): + if self.kwargs.get('quiet', False): + return self.output.start(self) def output_fail(self, exception=None): + if self.kwargs.get('quiet', False): + return self.output.fail(self, exception) def output_success(self): + if self.kwargs.get('quiet', False): + return self.output.success(self) def __repr__(self): @@ -130,15 +141,16 @@ class Action: return ' '.join([ self.output.colors['pink1'] + type(self).__name__ - + self.output.colors['reset'] + + self.output.colors['yellow'] ] + list(self.args) + [ f'{self.output.colors["blue"]}{k}{self.output.colors["gray"]}={self.output.colors["green2"]}{v}' for k, v in self.kwargs_output().items() ] + [self.output.colors['reset']]) def callable(self): + from ..targets import Localhost async def cb(*a, **k): - return await self(*a, **k) + return await Localhost(self, quiet=True)(*a, **k) return cb def kwargs_output(self): diff --git a/shlax/actions/copy.py b/shlax/actions/copy.py index a96881a..c325f03 100644 --- a/shlax/actions/copy.py +++ b/shlax/actions/copy.py @@ -2,9 +2,5 @@ from .base import Action class Copy(Action): - def __init__(self, *args): - self.src = args[:-1] - self.dst = args[-1] - - def call(self, *args, **kwargs): - self.copy(self.src, self.dst) + async def call(self, *args, **kwargs): + await self.copy(*self.args) diff --git a/shlax/actions/pip.py b/shlax/actions/pip.py index e9d763e..df41ec4 100644 --- a/shlax/actions/pip.py +++ b/shlax/actions/pip.py @@ -12,10 +12,10 @@ class Pip(Action): def __init__(self, *pip_packages, pip=None, requirements=None): self.pip_packages = pip_packages self.requirements = requirements + super().__init__(*pip_packages, pip=pip, requirements=requirements) async def call(self, *args, **kwargs): - breakpoint() - self.pip = await self.which(('pip3', 'pip', 'pip2')) + self.pip = await self.which('pip3', 'pip', 'pip2') if not self.pip: raise Exception('Could not find pip command') diff --git a/shlax/output.py b/shlax/output.py index 0a57039..1654283 100644 --- a/shlax/output.py +++ b/shlax/output.py @@ -58,8 +58,9 @@ class Output: def cmd(self, line): self( - self.colorize(251, '+ ') + self.colorize(251, '+') + '\x1b[1;38;5;15;48;5;244m' + + ' ' + self.highlight(line, 'bash') + self.colors['reset'], highlight=False diff --git a/shlax/strategies/script.py b/shlax/strategies/script.py index fe7d621..282f1fc 100644 --- a/shlax/strategies/script.py +++ b/shlax/strategies/script.py @@ -14,6 +14,7 @@ class Actions(list): self.append(action) def append(self, value): + value = copy.deepcopy(value) value.parent = self.owner value.status = 'pending' super().append(value) @@ -21,7 +22,7 @@ class Actions(list): class Script(Action): root = '/' - contextualize = ['shargs', 'exec', 'rexec', 'env', 'which'] + contextualize = ['shargs', 'exec', 'rexec', 'env', 'which', 'copy'] def __init__(self, *actions, **kwargs): super().__init__(**kwargs) @@ -77,3 +78,7 @@ class Script(Action): p = os.path.join(self.root, path[1:], c) if os.path.exists(p): return p[len(str(self.root)):] + + async def copy(self, *args): + args = ['cp', '-ra'] + list(args) + return await self.exec(*args) diff --git a/shlax/targets/buildah.py b/shlax/targets/buildah.py index 9a88560..203bc23 100644 --- a/shlax/targets/buildah.py +++ b/shlax/targets/buildah.py @@ -49,17 +49,27 @@ class Buildah(Localhost): async def config(self, line): """Run buildah config.""" - return await self.exec(f'buildah config {line} {self.ctr}') + return await self.exec(f'buildah config {line} {self.ctr}', buildah=False) - async def copy(self, src, dst): + async def mkdir(self, *dirs): + return await self.exec(*['mkdir', '-p'] + list(dirs)) + + async def copy(self, *args): """Run buildah copy to copy a file from host into container.""" - return await self.exec(f'buildah copy {self.ctr} {src} {self.mnt}{dst}') + src = args[:-1] + dst = args[-1] + await self.mkdir(dst) + + args = ['buildah', 'copy', self.ctr] + list( + [str(a) for a in src] + ) + [str(dst)] + return await self.exec(*args, buildah=False) async def mount(self, src, dst): """Mount a host directory into the container.""" target = self.mnt / str(dst)[1:] - await super().exec(f'mkdir -p {src} {target}') - await super().exec(f'mount -o bind {src} {target}') + await self.exec(f'mkdir -p {src} {target}') + await self.exec(f'mount -o bind {src} {target}') self.mounts[src] = dst async def umounts(self): @@ -88,18 +98,19 @@ class Buildah(Localhost): def __repr__(self): return f'Build' - async def call(self, *args, debug=False, **kwargs): - if Proc.test or os.getuid() == 0 or self.parent.parent: + @property + def _compatible(self): + return Proc.test or os.getuid() == 0 or getattr(self.parent, 'parent', None) + + async def call(self, *args, **kwargs): + if self._compatible: self.ctr = (await self.exec('buildah', 'from', self.base, buildah=False)).out self.mnt = Path((await self.exec('buildah', 'mount', self.ctr, buildah=False)).out) - result = await super().call(*args, **kwargs) - #await self.umounts() - #await self.umount() - await self.exec('buildah', 'rm', self.ctr, raises=False, buildah=False) - return result + return await super().call(*args, **kwargs) from shlax.cli import cli + debug = kwargs.get('debug', False) # restart under buildah unshare environment argv = [ 'buildah', 'unshare', @@ -123,3 +134,8 @@ class Buildah(Localhost): ) await proc.communicate() cli.exit_code = await proc.wait() + + async def clean(self, *args, **kwargs): + #await self.umounts() + #await self.umount() + await self.exec('buildah', 'rm', self.ctr, raises=False, buildah=False) diff --git a/tests/actions/test_base.py b/tests/actions/test_base.py index 17fbd32..eedca9d 100644 --- a/tests/actions/test_base.py +++ b/tests/actions/test_base.py @@ -4,6 +4,9 @@ inner = Run() other = Run('ls') middle = Buildah('alpine', inner, other) outer = Localhost(middle) +middle = outer.actions[0] +other = middle.actions[1] +inner = middle.actions[0] def test_action_init_args():