This repository has been archived on 2020-03-24. You can view files and clone it, but cannot push or open issues or pull requests.
quay/endpoints/api/image.py
Silas Sewell 9000169b53 Revert "Merge pull request #491 from jakedt/migratebackp2"
This reverts commit 7ad2522dbe, reversing
changes made to a0b191ffa1.
2015-09-28 16:09:22 -04:00

134 lines
4.5 KiB
Python

""" List and lookup repository images, and download image diffs. """
import json
from collections import defaultdict
from app import storage as store
from endpoints.api import (resource, nickname, require_repo_read, RepositoryParamResource,
format_date, NotFound, path_param)
from data import model
from util.cache import cache_control_flask_restful
def image_view(image, image_map, include_ancestors=True):
extended_props = image
if image.storage and image.storage.id:
extended_props = image.storage
command = extended_props.command
def docker_id(aid):
if not aid or not aid in image_map:
return ''
return image_map[aid].docker_image_id
image_data = {
'id': image.docker_image_id,
'created': format_date(extended_props.created),
'comment': extended_props.comment,
'command': json.loads(command) if command else None,
'size': extended_props.image_size,
'uploading': image.storage.uploading,
'sort_index': len(image.ancestors),
}
if include_ancestors:
# Calculate the ancestors string, with the DBID's replaced with the docker IDs.
ancestors = [docker_id(a) for a in image.ancestors.split('/')]
image_data['ancestors'] = '/'.join(ancestors)
return image_data
def historical_image_view(image, image_map):
ancestors = [image_map[a] for a in image.ancestors.split('/')[1:-1]]
normal_view = image_view(image, image_map)
normal_view['history'] = [image_view(parent, image_map, False) for parent in ancestors]
return normal_view
@resource('/v1/repository/<repopath:repository>/image/')
@path_param('repository', 'The full path of the repository. e.g. namespace/name')
class RepositoryImageList(RepositoryParamResource):
""" Resource for listing repository images. """
@require_repo_read
@nickname('listRepositoryImages')
def get(self, namespace, repository):
""" List the images for the specified repository. """
repo = model.repository.get_repository(namespace, repository)
if not repo:
raise NotFound()
all_images = model.image.get_repository_images_without_placements(repo)
all_tags = model.tag.list_repository_tags(namespace, repository)
tags_by_image_id = defaultdict(list)
found_image_ids = set()
for tag in all_tags:
tags_by_image_id[tag.image.docker_image_id].append(tag.name)
found_image_ids.add(str(tag.image.id))
found_image_ids.update(tag.image.ancestors.split('/')[1:-1])
image_map = {}
filtered_images = []
for image in all_images:
if str(image.id) in found_image_ids:
image_map[str(image.id)] = image
filtered_images.append(image)
def add_tags(image_json):
image_json['tags'] = tags_by_image_id[image_json['id']]
return image_json
return {
'images': [add_tags(image_view(image, image_map)) for image in filtered_images]
}
@resource('/v1/repository/<repopath:repository>/image/<image_id>')
@path_param('repository', 'The full path of the repository. e.g. namespace/name')
@path_param('image_id', 'The Docker image ID')
class RepositoryImage(RepositoryParamResource):
""" Resource for handling repository images. """
@require_repo_read
@nickname('getImage')
def get(self, namespace, repository, image_id):
""" Get the information available for the specified image. """
image = model.image.get_repo_image_extended(namespace, repository, image_id)
if not image:
raise NotFound()
# Lookup all the ancestor images for the image.
image_map = {}
for current_image in model.image.get_parent_images(namespace, repository, image):
image_map[str(current_image.id)] = current_image
return historical_image_view(image, image_map)
@resource('/v1/repository/<repopath:repository>/image/<image_id>/changes')
@path_param('repository', 'The full path of the repository. e.g. namespace/name')
@path_param('image_id', 'The Docker image ID')
class RepositoryImageChanges(RepositoryParamResource):
""" Resource for handling repository image change lists. """
@cache_control_flask_restful(max_age=60*60) # Cache for one hour
@require_repo_read
@nickname('getImageChanges')
def get(self, namespace, repository, image_id):
""" Get the list of changes for the specified image. """
image = model.image.get_repo_image_extended(namespace, repository, image_id)
if not image:
raise NotFound()
diffs_path = store.image_file_diffs_path(image.storage.uuid)
try:
response_json = json.loads(store.get_content(image.storage.locations, diffs_path))
return response_json
except IOError:
raise NotFound()