Package: piuparts Version: 0.84 Severity: normal Tags: patch I have written a patch for adding docker support on piuparts. A new option is introduced `--docker-image` e.g.
$ piuparts --docker-image debian:unstable package.deb Honestly I didn't do too much testing on this, I just have tried using the new feature of course and I have tried using schroot to check it's not breaking something. I am willing to help you if you need/want to do extra testing on this. The patch attached is made against origin/master. Cheers, -- TiN
diff --git a/piuparts.py b/piuparts.py index 3daba797..a13bd9fc 100644 --- a/piuparts.py +++ b/piuparts.py @@ -47,6 +47,7 @@ import os import tarfile import stat import re +import json import pickle import subprocess import traceback @@ -191,6 +192,7 @@ class Settings: self.skip_minimize = True self.minimize = False self.debfoster_options = None + self.docker_image = None # tests and checks self.no_install_purge_test = False self.no_upgrade_test = False @@ -769,7 +771,7 @@ class Chroot: def create(self, temp_tgz=None): """Create a chroot according to user's wishes.""" self.panic_handler_id = do_on_panic(self.remove) - if not settings.schroot: + if not settings.schroot and not settings.docker_image: self.create_temp_dir() if temp_tgz: @@ -782,10 +784,12 @@ class Chroot: self.setup_from_dir(settings.existing_chroot) elif settings.schroot: self.setup_from_schroot(settings.schroot) + elif settings.docker_image: + self.setup_from_docker(settings.docker_image) else: self.setup_minimal_chroot() - if not settings.schroot: + if not settings.schroot and not settings.docker_image: self.mount_proc() self.configure_chroot() @@ -807,7 +811,7 @@ class Chroot: self.run_scripts("post_chroot_unpack") self.run(["apt-get", "update"]) - if settings.basetgz or settings.schroot or settings.existing_chroot: + if settings.basetgz or settings.docker_image or settings.schroot or settings.existing_chroot: self.run(["apt-get", "-yf", "dist-upgrade"]) self.minimize() self.remember_available_md5() @@ -832,7 +836,10 @@ class Chroot: if settings.schroot: logging.debug("Terminate schroot session '%s'" % self.name) run(['schroot', '--end-session', '--chroot', "session:" + self.schroot_session]) - if not settings.schroot: + if settings.docker_image: + logging.debug("Destroy docker container '%s'" % self.docker_container) + run(['docker', 'rm', '-f', self.docker_container]) + if not settings.schroot and not settings.docker_image: run(['rm', '-rf', '--one-file-system', self.name]) if os.path.exists(self.name): create_file(os.path.join(self.name, ".piuparts.tmpdir"), "removal failed") @@ -840,6 +847,8 @@ class Chroot: elif settings.keep_tmpdir: if settings.schroot: logging.debug("Keeping schroot session %s at %s" % (self.schroot_session, self.name)) + elif settings.docker_image: + logging.debug("Keeping container %s" % self.docker_container) else: logging.debug("Keeping directory tree at %s" % self.name) dont_do_on_panic(self.panic_handler_id) @@ -892,6 +901,25 @@ class Chroot: self.name = output.strip() logging.info("New schroot session in '%s'" % self.name) + @staticmethod + def check_if_docker_storage_driver_is_supported(): + ret_code, output = run(['docker', 'info']) + if 'overlay2' not in output: + logging.error('Only overlay2 storage driver is supported') + panic() + + def setup_from_docker(self, docker_image): + self.check_if_docker_storage_driver_is_supported() + ret_code, output = run(['docker', 'run', '-d', '-it', docker_image, 'bash']) + if ret_code != 0: + logging.error("Couldn't start the container from '%s'" % docker_image) + panic() + self.docker_container = output.strip() + ret_code, output = run(['docker', 'inspect', self.docker_container]) + container_data = json.loads(output)[0] + self.name = container_data['GraphDriver']['Data']['MergedDir'] + logging.info("New container created '%s'" % self.docker_container) + def setup_from_lvm(self, lvm_volume): """Create a chroot by creating an LVM snapshot.""" self.lvm_base = os.path.dirname(lvm_volume) @@ -938,6 +966,12 @@ class Chroot: ["schroot", "--preserve-environment", "--run-session", "--chroot", "session:" + self.schroot_session, "--directory", "/", "-u", "root", "--"] + prefix + command, ignore_errors=ignore_errors, timeout=settings.max_command_runtime) + elif settings.docker_image: + return run( + ['docker', 'exec', self.docker_container,] + prefix + command, + ignore_errors=ignore_errors, + timeout=settings.max_command_runtime + ) else: return run(["chroot", self.name] + prefix + command, ignore_errors=ignore_errors, timeout=settings.max_command_runtime) @@ -1042,6 +1076,9 @@ class Chroot: def create_resolv_conf(self): """Update resolv.conf based on the current configuration in the host system. Strip comments and whitespace.""" + if settings.docker_image: + # Do nothing, docker already takes care of this + return full_name = self.relative("etc/resolv.conf") resolvconf = "" with open("/etc/resolv.conf", "r") as f: @@ -1624,8 +1661,12 @@ class Chroot: def check_for_no_processes(self, fail=None): """Check there are no processes running inside the chroot.""" - (status, output) = run(["lsof", "-w", "+D", self.name], ignore_errors=True) - count = len(output.split("\n")) - 1 + if settings.docker_image: + (status, output) = run(["docker", "top", self.docker_container]) + count = len(output.strip().split("\n")) - 2 # header + bash launched on container creation + else: + (status, output) = run(["lsof", "-w", "+D", self.name], ignore_errors=True) + count = len(output.split("\n")) - 1 if count > 0: if fail is None: fail = not settings.allow_database @@ -1637,6 +1678,9 @@ class Chroot: def terminate_running_processes(self): """Terminate all processes running in the chroot.""" + if settings.docker_image: + # docker takes care of this + return seen = [] while True: p = subprocess.Popen(["lsof", "-t", "+D", self.name], @@ -2726,6 +2770,10 @@ def parse_command_line(): help="Use schroot session named SCHROOT-NAME for the chroot, instead of building " + "a new one with debootstrap.") + parser.add_option("--docker-image", metavar="DOCKER-IMAGE", action="store", + help="Use docker image DOCKER-IMAGE for the chroot, instead of building " + + "a new one with debootstrap.") + parser.add_option("-m", "--mirror", action="append", metavar="URL", default=[], help="Which Debian mirror to use.") @@ -2948,6 +2996,7 @@ def parse_command_line(): if settings.minimize: settings.skip_minimize = False settings.debfoster_options = opts.debfoster_options.split() + settings.docker_image = opts.docker_image # tests and checks settings.no_install_purge_test = opts.no_install_purge_test settings.no_upgrade_test = opts.no_upgrade_test
signature.asc
Description: OpenPGP digital signature