From c38ad7e0897cb398fc42cace11f45dde42b7b550 Mon Sep 17 00:00:00 2001 From: jpic Date: Sun, 2 Aug 2020 20:10:52 +0200 Subject: [PATCH] Getting on par with docker-compose --- setup.py | 2 +- shlax/container.py | 43 +++++++++++++++++++++++++++++++++++--- shlax/pod.py | 52 +++++++++++++++++++++++++++++++++++++++++++++- shlax/podman.py | 18 ++++++++++++++++ 4 files changed, 110 insertions(+), 5 deletions(-) create mode 100644 shlax/podman.py diff --git a/setup.py b/setup.py index 3ef0693..b89a78a 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup( setup_requires='setupmeta', extras_require=dict( cli=[ - 'cli2>=2.2.2', + 'cli2>=2.3.0', ], test=[ 'pytest', diff --git a/shlax/container.py b/shlax/container.py index 6091704..79ed172 100644 --- a/shlax/container.py +++ b/shlax/container.py @@ -1,6 +1,7 @@ import copy import os +from .podman import Podman from .image import Image @@ -12,6 +13,7 @@ class Container: self.image = Image(self.image) self.volumes = volumes or {} self.env = env or {} + prefix = os.getcwd().split('/')[-1] repo = self.image.repository.replace('/', '-') if prefix == repo: @@ -19,8 +21,39 @@ class Container: else: self.name = '-'.join([prefix, repo]) + self.pod = None + + @property + def full_name(self): + if self.pod: + return '-'.join([self.pod.name, self.name]) + return self.name + async def up(self, target, *args): """Start the container foreground""" + podman = Podman(target) + if self.pod: + pod = None + for _ in await podman.pod.ps(): + if _['Name'] == self.pod.name: + pod = _ + break + if not pod: + await podman.pod.create('--name', self.pod.name) + args = list(args) + ['--pod', self.pod.name] + + # skip if already up + for result in await podman.ps('-a'): + for name in result['Names']: + if name == self.full_name: + if result['State'] == 'running': + target.output.info(f'{self.full_name} already running') + return + elif result['State'] == 'exited': + target.output.info(f'{self.full_name} starting') + await target.exec('podman', 'start', self.full_name) + return + cmd = [ 'podman', 'run', @@ -34,7 +67,7 @@ class Container: cmd += [ '--name', - self.name, + self.full_name, str(self.image), ] await target.exec(*cmd) @@ -45,11 +78,15 @@ class Container: async def stop(self, target): """Start the container""" - await target.exec('podman', 'stop', self.name) + await target.exec('podman', 'stop', self.full_name) + + async def logs(self, target): + """Start the container""" + await target.exec('podman', 'logs', self.full_name) async def down(self, target): """Start the container""" - await target.exec('podman', 'rm', '-f', self.name, raises=False) + await target.exec('podman', 'rm', '-f', self.full_name, raises=False) async def apply(self, target): """Start the container""" diff --git a/shlax/pod.py b/shlax/pod.py index 82da2af..e19c519 100644 --- a/shlax/pod.py +++ b/shlax/pod.py @@ -1,13 +1,21 @@ import cli2 +import json +import os from shlax.targets.base import Target from shlax.actions.parallel import Parallel +from .podman import Podman + class Pod: """Help text""" def __init__(self, **containers): self.containers = containers + for name, container in self.containers.items(): + container.pod = self + container.name = name + self.name = os.getcwd().split('/')[-1] async def _call(self, target, method, *names): methods = [ @@ -19,8 +27,50 @@ class Pod: async def build(self, target, *names): """Build container images""" - await self._call(target, 'build', *names) + if not Proc.test or os.getuid() == 0: + os.execvp('buildah', ['buildah', 'unshare'] + sys.argv) + else: + await self._call(target, 'build', *names) + + async def down(self, target, *names): + """Delete container images""" + await self._call(target, 'down', *names) async def start(self, target, *names): """Start container images""" await self._call(target, 'start', *names) + + async def logs(self, target, *names): + """Start container images""" + await self._call(target, 'logs', *names) + + async def ps(self, target): + """Show containers and volumes""" + containers = [] + names = [] + for container in await Podman(target).ps('-a'): + for name in container['Names']: + if name.startswith(self.name + '-'): + container['Name'] = name + containers.append(container) + names.append(name) + + for name, container in self.containers.items(): + full_name = '-'.join([self.name, container.name]) + if full_name in names: + continue + containers.append(dict( + Name=full_name, + State='not created', + )) + + cli2.Table( + ['Name', 'State'], + *[ + (container['Name'], container['State']) + for container in containers + ] + ).print() + + def __str__(self): + return f'Pod({self.name})' diff --git a/shlax/podman.py b/shlax/podman.py new file mode 100644 index 0000000..05d46e7 --- /dev/null +++ b/shlax/podman.py @@ -0,0 +1,18 @@ +import json + + +class Podman(list): + def __init__(self, target, *args): + self.target = target + super().__init__(args or ['podman']) + + def __getattr__(self, command): + if command.startswith('_'): + return super().__getattr__(command) + return Podman(self.target, *self + [command]) + + async def __call__(self, *args, **kwargs): + cmd = self + list(args) + [f'--{k}={v}' for k, v in kwargs.items()] + if 'ps' in cmd: + cmd += ['--format=json'] + return (await self.target.exec(*cmd, quiet=True)).json