X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/728fbdbae7d8e926f64a09d3f20aad6bdb67435e..d7e750680bbf5e655d7c986ce0cff550c8022ca4:/sdk/python/arvados/commands/keepdocker.py diff --git a/sdk/python/arvados/commands/keepdocker.py b/sdk/python/arvados/commands/keepdocker.py index 0c4930e039..c6bfc868d3 100644 --- a/sdk/python/arvados/commands/keepdocker.py +++ b/sdk/python/arvados/commands/keepdocker.py @@ -82,17 +82,31 @@ def docker_images(): list_proc.stdout.close() check_docker(list_proc, "images") -def find_image_hash(image_name, image_tag): - hash_search = image_name.lower() +def find_image_hashes(image_search, image_tag=None): + # Given one argument, search for Docker images with matching hashes, + # and return their full hashes in a set. + # Given two arguments, also search for a Docker image with the + # same repository and tag. If one is found, return its hash in a + # set; otherwise, fall back to the one-argument hash search. + # Returns None if no match is found, or a hash search is ambiguous. + hash_search = image_search.lower() hash_matches = set() for image in docker_images(): - if (image.repo == image_name) and (image.tag == image_tag): - return image.hash + if (image.repo == image_search) and (image.tag == image_tag): + return set([image.hash]) elif image.hash.startswith(hash_search): hash_matches.add(image.hash) - if len(hash_matches) == 1: - return hash_matches.pop() - return None + return hash_matches + +def find_one_image_hash(image_search, image_tag=None): + hashes = find_image_hashes(image_search, image_tag) + hash_count = len(hashes) + if hash_count == 1: + return hashes.pop() + elif hash_count == 0: + raise DockerError("no matching image found") + else: + raise DockerError("{} images match {}".format(hash_count, image_search)) def stat_cache_name(image_file): return getattr(image_file, 'name', image_file) + '.stat' @@ -143,14 +157,15 @@ def main(arguments=None): # Pull the image if requested, unless the image is specified as a hash # that we already have. - if args.pull and (find_image_hash(args.image, None) is None): + if args.pull and not find_image_hashes(args.image): pull_image(args.image, args.tag) - image_hash = find_image_hash(args.image, args.tag) - if image_hash is None: - print >>sys.stderr, "arv-keepdocker: No image found." + try: + image_hash = find_one_image_hash(args.image, args.tag) + except DockerError as error: + print >>sys.stderr, "arv-keepdocker:", error.message sys.exit(1) - elif not args.force: + if not args.force: # Abort if this image is already in Arvados. existing_links = arvados.api('v1').links().list( filters=[['link_class', '=', 'docker_image_hash'], @@ -161,7 +176,7 @@ def main(arguments=None): format(image_hash)] message.extend(link['head_uuid'] for link in existing_links) print >>sys.stderr, "\n".join(message) - sys.exit(1) + sys.exit(0) # Open a file for the saved image, and write it if needed. outfile_name = '{}.tar'.format(image_hash) @@ -188,8 +203,8 @@ def main(arguments=None): make_link('docker_image_hash', image_hash, **link_base) if not image_hash.startswith(args.image.lower()): - make_link('docker_image_repository', args.image, **link_base) - make_link('docker_image_tag', args.tag, **link_base) + make_link('docker_image_repo+tag', '{}:{}'.format(args.image, args.tag), + **link_base) # Clean up. image_file.close()