Add image ancestry and update the test db accordingly.

This commit is contained in:
yackob03 2013-09-30 15:30:00 -04:00
parent abdf731f7a
commit ea6df2b725
5 changed files with 43 additions and 14 deletions

View file

@ -89,6 +89,9 @@ class Image(BaseModel):
comment = CharField(null=True) comment = CharField(null=True)
repository = ForeignKeyField(Repository) repository = ForeignKeyField(Repository)
# '/' separated list of ancestory ids, e.g. /1/2/6/7/10/
ancestors = CharField(index=True, default='/', max_length=65535)
class Meta: class Meta:
database = db database = db
indexes = ( indexes = (

View file

@ -198,7 +198,7 @@ def set_image_checksum(image_id, repository, checksum):
def set_image_metadata(image_id, namespace_name, repository_name, def set_image_metadata(image_id, namespace_name, repository_name,
created_date_str, comment): created_date_str, comment, parent=None):
joined = Image.select().join(Repository) joined = Image.select().join(Repository)
image_list = list(joined.where(Repository.name == repository_name, image_list = list(joined.where(Repository.name == repository_name,
Repository.namespace == namespace_name, Repository.namespace == namespace_name,
@ -210,6 +210,10 @@ def set_image_metadata(image_id, namespace_name, repository_name,
fetched = image_list[0] fetched = image_list[0]
fetched.created = dateutil.parser.parse(created_date_str) fetched.created = dateutil.parser.parse(created_date_str)
fetched.comment = comment fetched.comment = comment
if parent:
fetched.ancestors = '%s%s/' % (parent.ancestors, parent.id)
fetched.save() fetched.save()
return fetched return fetched
@ -220,15 +224,6 @@ def get_repository_images(namespace_name, repository_name):
Repository.namespace == namespace_name) Repository.namespace == namespace_name)
def get_tag_images(namespace_name, repository_name, tag_name):
joined = Image.select().join(RepositoryTag).join(Repository)
fetched = list(joined.where(Repository.name == repository_name,
Repository.namespace == namespace_name,
RepositoryTag.name == tag_name))
return fetched
def list_repository_tags(namespace_name, repository_name): def list_repository_tags(namespace_name, repository_name):
select = RepositoryTag.select(RepositoryTag, Image) select = RepositoryTag.select(RepositoryTag, Image)
with_repo = select.join(Repository) with_repo = select.join(Repository)
@ -238,13 +233,33 @@ def list_repository_tags(namespace_name, repository_name):
def get_tag_image(namespace_name, repository_name, tag_name): def get_tag_image(namespace_name, repository_name, tag_name):
fetched = get_tag_images(namespace_name, repository_name, tag_name) joined = Image.select().join(RepositoryTag).join(Repository)
fetched = joined.where(Repository.name == repository_name,
Repository.namespace == namespace_name,
RepositoryTag.name == tag_name)
if not fetched: if not fetched:
raise DataModelException('Unable to find image for tag.') raise DataModelException('Unable to find image for tag.')
return fetched[0] return fetched[0]
def get_image_by_id(image_id):
return Image.get(Image.image_id == image_id)
def get_parent_images(image_obj):
""" Returns a list of parent Image objects in chronilogical order. """
parents = image_obj.ancestors
parent_db_ids = parents.strip('/').split('/')
or_clauses = [(Image.id == db_id) for db_id in parent_db_ids]
parent_images = Image.select().where(reduce(operator.or_, or_clauses))
id_to_image = {unicode(image.id): image for image in parent_images}
return [id_to_image[parent_id] for parent_id in parent_db_ids]
def create_or_update_tag(namespace_name, repository_name, tag_name, def create_or_update_tag(namespace_name, repository_name, tag_name,
tag_image_id): tag_image_id):
repo = Repository.get(Repository.name == repository_name, repo = Repository.get(Repository.name == repository_name,

View file

@ -188,10 +188,15 @@ def role_view(repo_perm_obj):
def list_tag_images(namespace, repository, tag): def list_tag_images(namespace, repository, tag):
permission = ReadRepositoryPermission(namespace, repository) permission = ReadRepositoryPermission(namespace, repository)
if permission.can() or model.repository_is_public(namespace, repository): if permission.can() or model.repository_is_public(namespace, repository):
images = model.get_tag_images(namespace, repository, tag) tag_image = model.get_tag_image(namespace, repository, tag)
parent_images = model.get_parent_images(tag_image)
parents = list(parent_images)
parents.reverse()
all_images = [tag_image] + parents
return jsonify({ return jsonify({
'images': [image_view(image) for image in images] 'images': [image_view(image) for image in all_images]
}) })
abort(403) # Permission denied abort(403) # Permission denied

View file

@ -290,8 +290,14 @@ def put_image_json(namespace, repository, image_id):
# If we reach that point, it means that this is a new image or a retry # If we reach that point, it means that this is a new image or a retry
# on a failed push # on a failed push
# save the metadata # save the metadata
if parent_id:
parent_obj = model.get_image_by_id(parent_id)
else:
parent_obj = None
model.set_image_metadata(image_id, namespace, repository, model.set_image_metadata(image_id, namespace, repository,
data.get('created'), data.get('comment')) data.get('created'), data.get('comment'),
parent_obj)
store.put_content(mark_path, 'true') store.put_content(mark_path, 'true')
store.put_content(json_path, request.data) store.put_content(json_path, request.data)
generate_ancestry(namespace, repository, image_id, parent_id) generate_ancestry(namespace, repository, image_id, parent_id)

BIN
test.db

Binary file not shown.