diff --git a/focker-compose.yml b/focker-compose.yml index 0a8905c..d76429c 100644 --- a/focker-compose.yml +++ b/focker-compose.yml @@ -9,12 +9,12 @@ jails: image: wordpress-5 mounts: test-volume2: /mnt/volume2 - test-volume: /mnt/volume1 + test-volume2: /mnt/volume1 ip4.addr: 127.0.1.1 volumes: test-volume2: {} - test-volume: {} + test-volume2: {} commands: backup: diff --git a/focker.py b/focker.py index 7ebc084..00c7cee 100644 --- a/focker.py +++ b/focker.py @@ -27,6 +27,9 @@ from .jail import command_jail_create, \ command_jail_tag, \ command_jail_untag, \ command_jail_prune +from .compose import \ + command_compose_build, \ + command_compose_run class ListForwarderFunctor(object): @@ -63,7 +66,7 @@ def create_parser(): # image subparsers = ListForwarder([ subparsers_top.add_parser(cmd).add_subparsers(dest='L2_command') \ - for cmd in ['image', 'i'] ]) + for cmd in ['image', 'img', 'im', 'i'] ]) subparsers.required = True parser = ListForwarder([subparsers.add_parser(cmd) for cmd in ['build', 'b']]) parser.set_defaults(func=command_image_build) @@ -148,7 +151,7 @@ def create_parser(): # volume subparsers = ListForwarder([ subparsers_top.add_parser(cmd).add_subparsers(dest='L2_command') \ - for cmd in ['volume', 'v'] ]) + for cmd in ['volume', 'vol', 'v'] ]) subparsers.required = True parser = ListForwarder([subparsers.add_parser(cmd) for cmd in ['create', 'c']]) parser.set_defaults(func=command_volume_create) @@ -170,6 +173,19 @@ def create_parser(): parser.set_defaults(func=command_volume_untag) parser.add_argument('tags', type=str, nargs='+') + # compose + subparsers = ListForwarder([ subparsers_top.add_parser(cmd).add_subparsers(dest='L2_command') \ + for cmd in ['compose', 'comp', 'c'] ]) + subparsers.required = True + parser = ListForwarder([subparsers.add_parser(cmd) for cmd in ['build', 'b']]) + parser.set_defaults(func=command_compose_build) + parser.add_argument('filename', type=str) + + parser = ListForwarder([subparsers.add_parser(cmd) for cmd in ['run', 'r']]) + parser.set_defaults(func=command_compose_run) + parser.add_argument('filename', type=str) + parser.add_argument('command', type=str) + return parser_top diff --git a/misc.py b/misc.py index f789ad7..d3fbc3b 100644 --- a/misc.py +++ b/misc.py @@ -1,4 +1,14 @@ import random +from .zfs import zfs_exists + def random_sha256_hexdigest(): return bytes([ random.randint(0, 255) for _ in range(32) ]).hex() + + +def find_prefix(head, tail): + for pre in range(7, len(tail)): + name = head + tail[:pre] + if not zfs_exists(name): + break + return name diff --git a/run.py b/run.py deleted file mode 100644 index e69de29..0000000 diff --git a/zfs.py b/zfs.py index bed3fb7..a20747a 100644 --- a/zfs.py +++ b/zfs.py @@ -4,7 +4,7 @@ import io import os -class AmbiguousReference(ValueError): +class AmbiguousValueError(ValueError): def __init__(self, msg): super().__init__(msg) @@ -34,24 +34,31 @@ def zfs_snapshot_by_tag_or_sha256(s, focker_type='image'): if len(lst) == 0: raise ValueError('Reference not found: ' + s) if len(lst) > 1: - raise AmbiguousReference('Ambiguous reference: ' + s) + raise AmbiguousValueError('Ambiguous reference: ' + s) return (lst[0][3], lst[0][0]) def zfs_find(reference, focker_type='image', zfs_type='filesystem'): poolname = zfs_poolname() lst = zfs_parse_output(['zfs', 'list', '-o', 'focker:sha256,focker:tags,type,name', '-H', '-t', zfs_type, '-r', poolname + '/focker/' + focker_type + 's']) - def match(sha256, tags, type, name): - if sha256.startswith(reference) or \ - any(map(lambda a: a.startswith(reference), tags.split(' '))) or \ - name.split('/')[-1].startswith(reference): + def match(sha256, tags, type, name, exact=False): + if exact: + predicate = lambda a: (a == reference) + else: + predicate = lambda a: a.startswith(reference) + if predicate(sha256) or \ + any(map(predicate, tags.split(' '))) or \ + predicate(name.split('/')[-1]): return True return False lst = list(filter(lambda a: match(*a), lst)) + exact_lst = list(filter(lambda a: match(*a, exact=True), lst)) if len(lst) == 0: raise ValueError('Reference not found: ' + reference) if len(lst) > 1: - raise AmbiguousReference('Ambiguous reference: ' + reference) + if len(exact_lst) == 1: + return (exact_lst[0][3], exact_lst[0][0]) + raise AmbiguousValueError('Ambiguous reference: ' + reference) return (lst[0][3], lst[0][0]) @@ -124,7 +131,7 @@ def zfs_snapshot_by_sha256(sha256, focker_type='image'): if len(lst) == 0: raise ValueError('Snapshot with given sha256 does not exist: ' + sha256) if len(lst) > 1: - raise AmbiguousReference('Ambiguous snapshot sha256: ' + sha256) + raise AmbiguousValueError('Ambiguous snapshot sha256: ' + sha256) return lst[0][1] @@ -163,7 +170,7 @@ def zfs_name(path): if len(lst) == 0: raise ValueError('Not a ZFS path') if len(lst) > 1: - raise AmbiguousReference('Ambiguous ZFS path') + raise AmbiguousValueError('Ambiguous ZFS path') return lst[0][0]