Fix activation when glare has uploading blobs

Currently user can't activate his artifact if glare
uploads data for other artifacts in the system.
This code fixes this behavior.

Change-Id: Ice4666b0368b86c1722651576116b08d99f6f045
Closes-bug: #1699503
This commit is contained in:
Mike Fedosin 2017-06-21 16:18:52 +03:00
parent dc954085e7
commit 84c31bac4c
3 changed files with 46 additions and 7 deletions

View File

@ -154,16 +154,16 @@ def _create_or_update(context, artifact_id, values, session):
artifact.blobs = _do_blobs(artifact, blobs)
artifact.updated_at = timeutils.utcnow()
if 'status' in values and values['status'] == 'active':
if session.query(
exists().where(
models.ArtifactBlob.status == 'saving' and
models.ArtifactBlob.artifact_id == artifact_id)
if 'status' in values:
if session.query(exists().where(and_(
models.ArtifactBlob.status == 'saving',
models.ArtifactBlob.artifact_id == artifact_id))
).one()[0]:
raise exception.Conflict(
"You cannot activate artifact if it has "
"You cannot change artifact status if it has "
"uploading blobs.")
artifact.activated_at = timeutils.utcnow()
if values['status'] == 'active':
artifact.activated_at = timeutils.utcnow()
artifact.update(values)
LOG.debug('Sending request to the database. '

View File

@ -95,6 +95,9 @@ class TestArtifactUpdate(base.BaseTestArtifactAPI):
# Deleting of the artifact leads to Conflict error
self.assertRaises(exc.Conflict, self.controller.delete,
self.req, 'sample_artifact', self.artifact['id'])
self.artifact = self.controller.show(
self.req, 'sample_artifact', self.artifact['id'])
self.assertEqual('drafted', self.artifact['status'])
def test_delete_deleted_artifact(self):
# Change status of the artifact to 'deleted'

View File

@ -196,3 +196,39 @@ class TestArtifactUpload(base.BaseTestArtifactAPI):
exc.BadRequest, self.controller.upload_blob,
self.req, 'sample_artifact', self.sample_artifact['id'],
'dict_of_blobs/', BytesIO(b'aaa'), 'application/octet-stream')
def test_parallel_uploading_and_activation(self):
"""
This test check whether it is possible to activate an artifact,
when it has uploading blobs.
"""
self.controller.upload_blob(
self.req, 'sample_artifact', self.sample_artifact['id'], 'blob',
BytesIO(b'aaa'), 'application/octet-stream')
self.sample_artifact = self.controller.show(
self.req, 'sample_artifact', self.sample_artifact['id'])
changes = [{'op': 'replace',
'path': '/string_required',
'value': 'ttt'}]
self.update_with_values(changes)
# Change status of the blob to 'saving'
self.sample_artifact['blob']['status'] = 'saving'
artifact_api.ArtifactAPI().update_blob(
self.req.context, self.sample_artifact['id'],
{'blob': self.sample_artifact['blob']})
self.sample_artifact = self.controller.show(
self.req, 'sample_artifact', self.sample_artifact['id'])
self.assertEqual('saving', self.sample_artifact['blob']['status'])
# activation of artifact with saving blobs lead to Conflict error
changes = [{'op': 'replace', 'path': '/status', 'value': 'active'}]
self.assertRaises(exc.Conflict, self.update_with_values, changes)
# create another artifact which doesn't have uploading blobs
values = {'name': 'ttt', 'version': '2.0', 'string_required': 'rrr'}
new_artifact = self.controller.create(
self.req, 'sample_artifact', values)
# activation is possible
res = self.update_with_values(changes, art_id=new_artifact['id'])
self.assertEqual('active', res['status'])