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'
# 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'],
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()