Porting to subprocess

This commit is contained in:
jpic 2020-02-03 02:17:45 +01:00
parent 65ea77cb5e
commit 7753175d6c
3 changed files with 78 additions and 61 deletions

View File

@ -1,35 +1,36 @@
import asyncio
import os
import subprocess
import textwrap import textwrap
from .script import Script from .script import Script
class BuildScript(Script): class Build(Script):
export = ('base', 'repo')
def __init__(self, container): def __init__(self, container):
super().__init__() super().__init__()
self.container = container self.container = container
for var in self.export: def append(self, value):
self.append(f'{var}="{container.variable(var)}"') res = []
for line in value.split('\n'):
if line.startswith('#') or not line.strip():
continue
res.append(self.unshare(line))
return '\n'.join(res)
self.append(''' async def unshare(self, line):
mounts=() print('+ buildah unshare ' + line)
umounts() { proc = await asyncio.create_subprocess_shell(
for i in "${mounts[@]}"; do 'buildah unshare ' + line,
umount $i stdout=asyncio.subprocess.PIPE,
mounts=("${mounts[@]/$i}") stderr=asyncio.subprocess.PIPE,
done ).decode('utf8')
buildah unmount $ctr stdout, stderr = await proc.communicate()
trap - 0 return stdout
}
trap umounts 0
ctr=$(buildah from $base)
mnt=$(buildah mount $ctr)
''')
def config(self, line): def config(self, line):
self.append(f'buildah config {line} $ctr') self.append(f'buildah config {line} {self.ctr}')
def _run(self, cmd, inject=False): def _run(self, cmd, inject=False):
user = self.container.variable('username') user = self.container.variable('username')
@ -44,23 +45,29 @@ class BuildScript(Script):
break break
if heredoc: if heredoc:
_cmd = ' '.join(['bash -eux <<__EOF\n', _cmd.strip(), '\n__EOF']) _cmd = ''.join(['bash -eux <<__EOF\n', _cmd.strip(), '\n__EOF'])
if cmd.startswith('sudo '): if cmd.startswith('sudo '):
return f'buildah run --user root $ctr -- {_cmd}' return f'buildah run --user root {self.ctr} -- {_cmd}'
elif user and self.container.variable('user_created'): elif user and self.container.variable('user_created'):
return f'buildah run --user {user} $ctr -- {_cmd}' return f'buildah run --user {user} {self.ctr} -- {_cmd}'
else: else:
return f'buildah run $ctr -- {_cmd}' return f'buildah run {self.ctr} -- {_cmd}'
def run(self, cmd): def run(self, cmd):
self.append(self._run(cmd)) self.append(self._run(cmd))
def copy(self, src, dst): def copy(self, src, dst):
self.append(f'buildah copy $ctr {src} {dst}') self.append(f'buildah copy {self.ctr} {src} {dst}')
def mount(self, src, dst): def mount(self, src, dst):
self.run('sudo mkdir -p ' + dst) self.run('sudo mkdir -p ' + dst)
self.append('mkdir -p ' + src) self.append('mkdir -p ' + src)
self.append(f'mount -o bind {src} $mnt{dst}') self.append(f'mount -o bind {src} {self.mnt}{dst}')
self.append('mounts=("$mnt' + dst + '" "${mounts[@]}")') #self.append('mounts=("$mnt' + dst + '" "${mounts[@]}")')
self.mounts.append((src, dst))
def umounts(self):
for src, dst in self.mounts:
self.append('buildah unmount ' + dst)
self.append('buildah unmount ' + self.ctr)

View File

@ -42,17 +42,8 @@ async def build(*services, **kwargs):
else: else:
services = console_script.pod.services services = console_script.pod.services
for name, service in services.items():
container = service.container
if not container.variable('base'):
continue
script = f'.podctl_build_{name}.sh'
with open(script, 'w+') as f:
f.write(str(container.script('build')))
loop = asyncio.events.get_event_loop() loop = asyncio.events.get_event_loop()
debug = console_script.parser.options.get('debug', False)
def protocol_factory(): def protocol_factory():
return BuildStreamProtocol( return BuildStreamProtocol(
service, service,
@ -60,24 +51,11 @@ async def build(*services, **kwargs):
loop=loop, loop=loop,
) )
if os.getenv('BUILDAH_ISOLATION') == 'chroot': for name, service in services.items():
prefix = '' container = service.container
else: if not container.variable('base'):
prefix = 'buildah unshare ' continue
x = 'x' if console_script.parser.options.get('debug', False) else '' await container.build(loop, protocol_factory)
transport, protocol = await loop.subprocess_shell(
protocol_factory,
prefix + f'bash -eu{x} {script}',
)
print('+ ' + prefix + f' bash -eux {script}')
procs.append(asyncio.subprocess.Process(
transport,
protocol,
loop,
))
for proc in procs:
await proc.communicate()
for proc in procs: for proc in procs:
if proc.returncode != 0: if proc.returncode != 0:

View File

@ -1,8 +1,40 @@
from .build import BuildScript import os
from .build import Build
from .visitable import Visitable from .visitable import Visitable
class Container(Visitable): class Container(Visitable):
default_scripts = dict( default_scripts = dict(
build=BuildScript, build=Build,
) )
def script(self, name):
self.packages = []
for visitor in self.visitors:
self.packages += getattr(visitor, 'packages', [])
return super().script(name)
def script_run(self, name, debug):
script = f'.podctl_build_{name}.sh'
with open(script, 'w+') as f:
f.write(str(self.script('build')))
if os.getenv('BUILDAH_ISOLATION') == 'chroot':
prefix = ''
else:
prefix = 'buildah unshare '
x = 'x' if debug else ''
return prefix + f'bash -eu{x} {script}'
async def build(self, loop, protocol_factory):
transport, protocol = await loop.subprocess_shell(
protocol_factory,
cmd,
)
await asyncio.subprocess.Process(
transport,
protocol,
loop,
).communicate()