| @@ -2,5 +2,5 @@ base: freebsd-12.1 | |||||
| steps: | steps: | ||||
| - run: | | - run: | | ||||
| pkg install python3 && \ | |||||
| pkg install py37-pip | |||||
| pkg -y install -y python3 && \ | |||||
| pkg -y install -y py37-pip | |||||
| @@ -1,6 +1,8 @@ | |||||
| from .zfs import * | from .zfs import * | ||||
| import os | import os | ||||
| import yaml | import yaml | ||||
| from .steps import create_step | |||||
| from .snapshot import new_snapshot | |||||
| def process_step(step, name): | def process_step(step, name): | ||||
| @@ -18,13 +20,37 @@ def process_steps(steps, name): | |||||
| def build(spec): | def build(spec): | ||||
| if 'base' not in 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 = 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]) | root = '/'.join(base.split('/')[:-1]) | ||||
| print('base:', base, 'root:', root) | 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): | def command_image_build(args): | ||||
| fname = os.path.join(args.focker_dir, 'Fockerfile') | fname = os.path.join(args.focker_dir, 'Fockerfile') | ||||
| @@ -1,4 +1,6 @@ | |||||
| import subprocess | import subprocess | ||||
| def jail_run(path, command): | 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) | |||||
| @@ -1,4 +1,4 @@ | |||||
| from zfs import * | |||||
| from .zfs import * | |||||
| def new_snapshot(base, fun, name): | def new_snapshot(base, fun, name): | ||||
| @@ -15,4 +15,6 @@ def new_snapshot(base, fun, name): | |||||
| zfs_run(['zfs', 'destroy', name]) | zfs_run(['zfs', 'destroy', name]) | ||||
| raise | raise | ||||
| zfs_run(['zfs', 'set', 'readonly=on', name]) | 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 | |||||
| @@ -1,6 +1,6 @@ | |||||
| import hashlib | import hashlib | ||||
| import json | import json | ||||
| from jail import jail_run | |||||
| from .jail import jail_run | |||||
| import shutil | import shutil | ||||
| @@ -31,7 +31,7 @@ class RunStep(object): | |||||
| def execute(self, path): | def execute(self, path): | ||||
| spec = self.spec | spec = self.spec | ||||
| if isinstance(spec, list) | |||||
| if isinstance(spec, list): | |||||
| spec = ' && ' .join(self.spec) | spec = ' && ' .join(self.spec) | ||||
| jail_run(path, spec) | jail_run(path, spec) | ||||
| @@ -29,7 +29,7 @@ def zfs_snapshot_by_tag_or_sha256(s): | |||||
| raise ValueError('Reference not found: ' + s) | raise ValueError('Reference not found: ' + s) | ||||
| if len(lst) > 1: | if len(lst) > 1: | ||||
| raise ValueError('Ambiguous reference: ' + s) | raise ValueError('Ambiguous reference: ' + s) | ||||
| return lst[0][3] | |||||
| return (lst[0][3], lst[0][0]) | |||||
| def zfs_clone(name, target_name): | def zfs_clone(name, target_name): | ||||
| @@ -44,6 +44,16 @@ def zfs_exists(name): | |||||
| return True | 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(): | def zfs_init(): | ||||
| poolname = zfs_parse_output(['zfs', 'list', '-H', '/']) | poolname = zfs_parse_output(['zfs', 'list', '-H', '/']) | ||||
| if len(poolname) == 0: | if len(poolname) == 0: | ||||