diff --git a/.gitignore b/.gitignore index 52f83a0..d8329a9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ __pycache__ /mymailmap /*.shar /example/gitea/x +.pytest_cache/ diff --git a/focker/bootstrap.py b/focker/bootstrap.py index 527d189..4e0f833 100644 --- a/focker/bootstrap.py +++ b/focker/bootstrap.py @@ -9,7 +9,7 @@ from .zfs import zfs_poolname, \ def command_bootstrap(args): version = subprocess.check_output(['freebsd-version']).decode('utf-8') print('FreeBSD version:', version) - tags = [ 'freebsd-' + version.split('-')[0], 'freebsd-latest' ] + tags = args.tags or [ 'freebsd-' + version.split('-')[0], 'freebsd-latest' ] sha256 = hashlib.sha256(('FreeBSD ' + version).encode('utf-8')).hexdigest() poolname = zfs_poolname() name = find_prefix(poolname + '/focker/images/', sha256) @@ -17,6 +17,7 @@ def command_bootstrap(args): zfs_tag(name, tags) res = subprocess.run(['bsdinstall', 'jail', zfs_mountpoint(name)]) if res.returncode != 0: + zfs_run(['zfs', 'destroy', '-r', '-f', name]) raise ValueError('bsdinstall failed') subprocess.check_output(['zfs', 'set', 'rdonly=on', name]) subprocess.check_output(['zfs', 'snapshot', name + '@1']) diff --git a/focker/focker.py b/focker/focker.py index aacbf09..240fdff 100644 --- a/focker/focker.py +++ b/focker/focker.py @@ -78,6 +78,7 @@ def create_parser(): parser = ListForwarder([subparsers_top.add_parser(cmd) for cmd in ['bootstrap', 'boot', 'bs']]) parser.set_defaults(func=command_bootstrap) + parser.add_argument('--tags', '-t', type=str, nargs='+', default=None) # image subparsers = ListForwarder([ subparsers_top.add_parser(cmd).add_subparsers(dest='L2_command') \ @@ -111,6 +112,7 @@ def create_parser(): parser.add_argument('reference', type=str) # parser.add_argument('--remove-children', '-r', action='store_true') parser.add_argument('--remove-dependents', '-R', action='store_true') + parser.add_argument('--force', '-f', action='store_true') # jail subparsers = ListForwarder([ subparsers_top.add_parser(cmd).add_subparsers(dest='L2_command') \ diff --git a/focker/image.py b/focker/image.py index f94e0d1..9f128bf 100644 --- a/focker/image.py +++ b/focker/image.py @@ -162,8 +162,15 @@ def command_image_prune(args): def command_image_remove(args): - snap, snap_sha256 = zfs_find(args.reference, focker_type='image', - zfs_type='snapshot') + try: + snap, snap_sha256 = zfs_find(args.reference, focker_type='image', + zfs_type='snapshot') + except AmbiguousValueError: + raise + except ValueError: + if args.force: + return + raise ds = snap.split('@')[0] command = ['zfs', 'destroy', '-r', '-f'] #if args.remove_children: @@ -171,5 +178,7 @@ def command_image_remove(args): if args.remove_dependents: command.append('-R') command.append(ds) - subprocess.run(command) + res = subprocess.run(command) + if res.returncode != 0: + raise RuntimeError('zfs destroy failed') # zfs_run(['zfs', 'destroy', ds]) diff --git a/tests/test_bootstrap.py b/tests/test_bootstrap.py new file mode 100644 index 0000000..516bb02 --- /dev/null +++ b/tests/test_bootstrap.py @@ -0,0 +1,13 @@ +import subprocess +from focker.zfs import * +import re + + +def test_bootstrap(): + subprocess.run(['focker', 'image', 'remove', '--force', 'test-focker-bootstrap']) + subprocess.run(['focker', 'bootstrap', '--tags', 'test-focker-bootstrap']) + name, sha256 = zfs_find('test-focker-bootstrap', focker_type='volume') + assert len(name) >= 7 + assert re.search('[a-f]', name[:7]) + assert len(sha256) == 64 + assert name == sha256[:len(name)]