diff --git a/Fockerfile b/Fockerfile index 7ab82e7..15371fa 100644 --- a/Fockerfile +++ b/Fockerfile @@ -2,5 +2,5 @@ base: freebsd-12.1 steps: - run: | - pkg install python3 && \ - pkg install py37-pip + pkg -y install -y python3 && \ + pkg -y install -y py37-pip diff --git a/image.py b/image.py index 66957fc..87c3d5b 100644 --- a/image.py +++ b/image.py @@ -1,6 +1,8 @@ from .zfs import * import os import yaml +from .steps import create_step +from .snapshot import new_snapshot def process_step(step, name): @@ -18,13 +20,37 @@ def process_steps(steps, name): def build(spec): if 'base' not in spec: - raise ValueError('Missing base specification') + raise ValueError('Missing base in specification') + + if 'steps' not in spec: + raise ValueError('Missing steps in specification') + base = spec['base'] - base = zfs_snapshot_by_tag_or_sha256(base) + base, base_sha256 = zfs_snapshot_by_tag_or_sha256(base) root = '/'.join(base.split('/')[:-1]) print('base:', base, 'root:', root) + steps = spec['steps'] + if not isinstance(steps, list): + steps = [ steps ] + + for st in steps: + st = create_step(st) + st_sha256 = st.hash(base_sha256) + for pre in range(7, 64): + name = root + '/' + st_sha256[:pre] + if not zfs_exists(name): + break + snap_name = new_snapshot(base, lambda: st.execute(zfs_mountpoint(name)), name) + feed = { + 'focker:sha256': st_sha256 + } + zfs_tag(name, feed) + # zfs_tag(snap_name, feed) + base = snap_name + base_sha256 = st_sha256 + def command_image_build(args): fname = os.path.join(args.focker_dir, 'Fockerfile') diff --git a/jail.py b/jail.py index e079650..b64643a 100644 --- a/jail.py +++ b/jail.py @@ -1,4 +1,6 @@ import subprocess def jail_run(path, command): - subprocess.check_output(['jail', '-c', 'path=' + path, 'command', '/bin/sh', '-c', command) + command = ['jail', '-c', 'interface=lo1', 'ip4.addr=127.0.1.0', 'path=' + path, 'command', '/bin/sh', '-c', command] + print('Running:', ' '.join(command)) + subprocess.check_output(command) diff --git a/snapshot.py b/snapshot.py index a6115c6..72bb32b 100644 --- a/snapshot.py +++ b/snapshot.py @@ -1,4 +1,4 @@ -from zfs import * +from .zfs import * def new_snapshot(base, fun, name): @@ -15,4 +15,6 @@ def new_snapshot(base, fun, name): zfs_run(['zfs', 'destroy', name]) raise zfs_run(['zfs', 'set', 'readonly=on', name]) - zfs_run(['zfs', 'snapshot', name + '@1']) + snap_name = name + '@1' + zfs_run(['zfs', 'snapshot', snap_name]) + return snap_name diff --git a/steps.py b/steps.py index 196e762..61877bb 100644 --- a/steps.py +++ b/steps.py @@ -1,6 +1,6 @@ import hashlib import json -from jail import jail_run +from .jail import jail_run import shutil @@ -31,7 +31,7 @@ class RunStep(object): def execute(self, path): spec = self.spec - if isinstance(spec, list) + if isinstance(spec, list): spec = ' && ' .join(self.spec) jail_run(path, spec) diff --git a/zfs.py b/zfs.py index a7fe91d..adc6d56 100644 --- a/zfs.py +++ b/zfs.py @@ -29,7 +29,7 @@ def zfs_snapshot_by_tag_or_sha256(s): raise ValueError('Reference not found: ' + s) if len(lst) > 1: raise ValueError('Ambiguous reference: ' + s) - return lst[0][3] + return (lst[0][3], lst[0][0]) def zfs_clone(name, target_name): @@ -44,6 +44,16 @@ def zfs_exists(name): return True +def zfs_tag(name, props): + for (k, v) in props.items(): + zfs_run(['zfs', 'set', k + '=' + v, name]) + + +def zfs_mountpoint(name): + lst = zfs_parse_output(['zfs', 'list', '-o', 'mountpoint', '-H', name]) + return lst[0][0] + + def zfs_init(): poolname = zfs_parse_output(['zfs', 'list', '-H', '/']) if len(poolname) == 0: