Raise a 409 if we try to insert a tag twice at the same time

Also fixes handling of labels for existing manifests

Fixes #1775
This commit is contained in:
Joseph Schorr 2016-08-29 11:58:18 -04:00
parent 3f459523c4
commit 357005e33f
5 changed files with 36 additions and 12 deletions

View file

@ -2,8 +2,9 @@ import logging
from uuid import uuid4
from peewee import IntegrityError
from data.model import (image, db_transaction, DataModelException, _basequery,
InvalidManifestException)
InvalidManifestException, TagAlreadyCreatedException)
from data.database import (RepositoryTag, Repository, Image, ImageStorage, Namespace, TagManifest,
RepositoryNotification, Label, TagManifestLabel, get_epoch_timestamp,
db_for_update)
@ -96,8 +97,12 @@ def create_or_update_tag(namespace_name, repository_name, tag_name, tag_docker_i
except Image.DoesNotExist:
raise DataModelException('Invalid image with id: %s' % tag_docker_image_id)
return RepositoryTag.create(repository=repo, image=image_obj, name=tag_name,
lifetime_start_ts=now_ts, reversion=reversion)
try:
return RepositoryTag.create(repository=repo, image=image_obj, name=tag_name,
lifetime_start_ts=now_ts, reversion=reversion)
except IntegrityError:
msg = 'Tag with name %s and lifetime start %s under repository %s/%s already exists'
raise TagAlreadyCreatedException(msg % (tag_name, now_ts, namespace_name, repository_name))
def create_temporary_hidden_tag(repo, image_obj, expiration_s):
@ -255,19 +260,16 @@ def revert_tag(repo_obj, tag_name, docker_image_id):
def store_tag_manifest(namespace, repo_name, tag_name, docker_image_id, manifest_digest,
manifest_data):
""" Stores a tag manifest for a specific tag name in the database. Returns the TagManifest
object, as well as a boolean indicating whether the TagManifest was created or updated.
object, as well as a boolean indicating whether the TagManifest was created.
"""
with db_transaction():
tag = create_or_update_tag(namespace, repo_name, tag_name, docker_image_id)
try:
manifest = TagManifest.get(digest=manifest_digest)
if manifest.tag == tag:
return manifest, False
manifest.tag = tag
manifest.save()
return manifest, True
return manifest, False
except TagManifest.DoesNotExist:
return TagManifest.create(tag=tag, digest=manifest_digest, json_data=manifest_data), True