From 65ea77cb5ee23c0f3a935b0519a7873e253afd8e Mon Sep 17 00:00:00 2001 From: jpic Date: Mon, 3 Feb 2020 02:17:18 +0100 Subject: [PATCH] Add DumbInit, Template modules, and refactor Packages --- podctl/visitors/__init__.py | 2 + podctl/visitors/dumbinit.py | 15 +++++++ podctl/visitors/packages.py | 87 +++++++++++++++++++++---------------- podctl/visitors/template.py | 20 +++++++++ 4 files changed, 87 insertions(+), 37 deletions(-) create mode 100644 podctl/visitors/dumbinit.py create mode 100644 podctl/visitors/template.py diff --git a/podctl/visitors/__init__.py b/podctl/visitors/__init__.py index c98d50c..c256b53 100644 --- a/podctl/visitors/__init__.py +++ b/podctl/visitors/__init__.py @@ -3,9 +3,11 @@ from .cmd import Cmd # noqa from .commit import Commit # noqa from .config import Config # noqa from .copy import Copy # noqa +from .dumbinit import DumbInit # noqa from .npm import Npm # noqa from .mount import Mount # noqa from .packages import Packages # noqa from .pip import Pip # noqa from .run import Run # noqa +from .template import Template # noqa from .user import User # noqa diff --git a/podctl/visitors/dumbinit.py b/podctl/visitors/dumbinit.py new file mode 100644 index 0000000..d98c1a7 --- /dev/null +++ b/podctl/visitors/dumbinit.py @@ -0,0 +1,15 @@ +import re +import shlex + +from .packages import Packages + + +class DumbInit: + packages = ['dumb-init'] + + def __init__(self, cmd): + self.cmd = cmd + + def post_build(self, script): + cmd = '--cmd "dumb-init bash -euxc \'%s\'"' % self.cmd + script.config(cmd) diff --git a/podctl/visitors/packages.py b/podctl/visitors/packages.py index 0c714dc..60ae617 100644 --- a/podctl/visitors/packages.py +++ b/podctl/visitors/packages.py @@ -1,5 +1,6 @@ import os import subprocess +from textwrap import dedent class Packages: @@ -27,8 +28,14 @@ class Packages: ) def __init__(self, *packages, **kwargs): - self.packages = list(packages) + self.packages = list([ + dedent(l).strip().replace('\n', ' ') for l in packages + ]) self.mgr = kwargs.pop('mgr') if 'mgr' in kwargs else None + if 'CACHE_DIR' in os.environ: + self.cache = os.path.join(os.getenv('CACHE_DIR'), self.mgr) + else: + self.cache = os.path.join(os.getenv('HOME'), '.cache', self.mgr) def pre_build(self, script): base = script.container.variable('base') @@ -48,41 +55,47 @@ class Packages: raise Exception('Packages does not yet support this distro') def build(self, script): - if 'CACHE_DIR' in os.environ: - cache = os.path.join(os.getenv('CACHE_DIR'), self.mgr) - else: - cache = os.path.join(os.getenv('HOME'), '.cache', self.mgr) + if not getattr(script.container, '_packages_upgraded', None): + # run pkgmgr_setup functions ie. apk_setup + getattr(self, self.mgr + '_setup')(script) + # first run on container means inject visitor packages + self.packages += script.container.packages + script.run(self.cmds['upgrade']) + script.container._packages_upgraded = True - if self.mgr == 'apk': - script.mount(cache, f'/var/cache/{self.mgr}') - # special step to enable apk cache - script.run('ln -s /var/cache/apk /etc/apk/cache') - script.append(f''' - old="$(find .cache/apk/ -name APKINDEX.* -mtime +3)" - if [ -n "$old" ] || ! ls .cache/apk/APKINDEX.*; then - {script._run(self.cmds['update'])} - else - echo Cache recent enough, skipping index update. - fi - ''') - elif self.mgr == 'dnf': - script.mount(cache, f'/var/cache/{self.mgr}') - script.run('sh -c "echo keepcache=True >> /etc/dnf/dnf.conf"') - elif self.mgr == 'apt': - cache = cache + '/$(source $mnt/etc/os-release; echo $VERSION_CODENAME)/' # noqa - script.run('sudo rm /etc/apt/apt.conf.d/docker-clean') - cache_archives = os.path.join(cache, 'archives') - script.mount(cache_archives, f'/var/cache/apt/archives') - cache_lists = os.path.join(cache, 'lists') - script.mount(cache_lists, f'/var/lib/apt/lists') - script.append(f''' - old="$(find {cache_lists} -name lastup -mtime +3)" - if [ -n "$old" ] || ! ls {cache_lists}/lastup; then - {script._run(self.cmds['update'])} - touch {cache_lists}/lastup - else - echo Cache recent enough, skipping index update. - fi - ''') - script.run(self.cmds['upgrade']) script.run(' '.join([self.cmds['install']] + self.packages)) + + def apk_setup(self, script): + script.mount(self.cache, f'/var/cache/{self.mgr}') + # special step to enable apk cache + script.run('ln -s /var/cache/apk /etc/apk/cache') + script.append(f''' + old="$(find .cache/apk/ -name APKINDEX.* -mtime +3)" + if [ -n "$old" ] || ! ls .cache/apk/APKINDEX.*; then + {script._run(self.cmds['update'])} + else + echo Cache recent enough, skipping index update. + fi + ''') + + def dnf_setup(self, script): + script.mount(self.cache, f'/var/cache/{self.mgr}') + script.run('sh -c "echo keepcache=True >> /etc/dnf/dnf.conf"') + + def apt_setup(self, script): + cache = self.cache + '/$(source $mnt/etc/os-release; echo $VERSION_CODENAME)/' # noqa + script.run('sudo rm /etc/apt/apt.conf.d/docker-clean') + cache_archives = os.path.join(self.cache, 'archives') + script.mount(cache_archives, f'/var/cache/apt/archives') + cache_lists = os.path.join(self.cache, 'lists') + script.mount(cache_lists, f'/var/lib/apt/lists') + script.append(f''' + old="$(find {cache_lists} -name lastup -mtime +3)" + if [ -n "$old" ] || ! ls {cache_lists}/lastup; then + until [ -z $(lsof /var/lib/dpkg/lock) ]; do sleep 1; done + {script._run(self.cmds['update'])} + touch {cache_lists}/lastup + else + echo Cache recent enough, skipping index update. + fi + ''') diff --git a/podctl/visitors/template.py b/podctl/visitors/template.py new file mode 100644 index 0000000..00f702d --- /dev/null +++ b/podctl/visitors/template.py @@ -0,0 +1,20 @@ +from textwrap import dedent + + +CMD = '''cat < {target} +{script} +EOF''' + +class Template: + def __init__(self, target, *lines, **variables): + self.target = target + self.lines = lines + self.variables = variables + + def build(self, script): + self.script = '\n'.join([ + dedent(l).strip() for l in self.lines + ]).format(**self.variables) + script.run(CMD.strip().format(**self.__dict__)) + if self.script.startswith('#!'): + script.run('sudo chmod +x ' + self.target)