Disallow image uploads in v2 API when data exists
When data has already been uploaded for an image (determined by the existence of a location attribute), reject any subsequent requests to upload data with a 409 HTTP error code. * Related to bp api-v2-image-upload Change-Id: I0c4d2ebf548862ecb9c760bac9e96348f8377567
This commit is contained in:
parent
793bb61005
commit
f9afe586b6
@ -43,9 +43,12 @@ class ImageDataController(base.Controller):
|
||||
|
||||
def upload(self, req, image_id, data):
|
||||
self._get_image(req.context, image_id)
|
||||
size = len(data)
|
||||
location, size, checksum = self.store_api.add_to_backend(
|
||||
'file', image_id, data, size)
|
||||
try:
|
||||
location, size, checksum = self.store_api.add_to_backend(
|
||||
'file', image_id, data, len(data))
|
||||
except exception.Duplicate:
|
||||
raise webob.exc.HTTPConflict()
|
||||
|
||||
self.db_api.image_update(req.context, image_id, {'location': location})
|
||||
|
||||
def download(self, req, image_id):
|
||||
|
@ -140,3 +140,36 @@ class TestImages(functional.FunctionalTest):
|
||||
self.assertEqual(0, len(images))
|
||||
|
||||
self.stop_servers()
|
||||
|
||||
def test_upload_duplicate_data(self):
|
||||
# Create an image
|
||||
path = self._url('/v2/images')
|
||||
headers = self._headers({'content-type': 'application/json'})
|
||||
data = json.dumps({'name': 'image-1'})
|
||||
response = requests.post(path, headers=headers, data=data)
|
||||
self.assertEqual(200, response.status_code)
|
||||
|
||||
# Returned image entity should have a generated id
|
||||
image = json.loads(response.text)['image']
|
||||
image_id = image['id']
|
||||
|
||||
# Upload some image data
|
||||
path = self._url('/v2/images/%s/file' % image_id)
|
||||
headers = self._headers()
|
||||
response = requests.put(path, headers=headers, data='ZZZZZ')
|
||||
self.assertEqual(200, response.status_code)
|
||||
|
||||
# Uploading duplicate data should be rejected with a 409
|
||||
path = self._url('/v2/images/%s/file' % image_id)
|
||||
headers = self._headers()
|
||||
response = requests.put(path, headers=headers, data='XXX')
|
||||
self.assertEqual(409, response.status_code)
|
||||
|
||||
# Data should not have been overwritten
|
||||
path = self._url('/v2/images/%s/file' % image_id)
|
||||
headers = self._headers()
|
||||
response = requests.get(path, headers=headers)
|
||||
self.assertEqual(200, response.status_code)
|
||||
self.assertEqual(response.text, 'ZZZZZ')
|
||||
|
||||
self.stop_servers()
|
||||
|
@ -52,7 +52,7 @@ class FakeDB(object):
|
||||
|
||||
def __init__(self):
|
||||
self.images = {
|
||||
UUID1: self._image_format(UUID1, location='1'),
|
||||
UUID1: self._image_format(UUID1, location=UUID1),
|
||||
UUID2: self._image_format(UUID2),
|
||||
}
|
||||
self.members = {
|
||||
@ -180,8 +180,7 @@ class FakeDB(object):
|
||||
class FakeStoreAPI(object):
|
||||
def __init__(self):
|
||||
self.data = {
|
||||
'1': ('XXX', 3),
|
||||
'2': ('FFFFF', 5),
|
||||
UUID1: ('XXX', 3),
|
||||
}
|
||||
|
||||
def create_stores(self, conf):
|
||||
@ -199,7 +198,8 @@ class FakeStoreAPI(object):
|
||||
return self.get_from_backend(location)[1]
|
||||
|
||||
def add_to_backend(self, scheme, image_id, data, size):
|
||||
location = utils.generate_uuid()
|
||||
self.data[location] = (data, size)
|
||||
if image_id in self.data:
|
||||
raise exception.Duplicate()
|
||||
self.data[image_id] = (data, size)
|
||||
checksum = 'Z'
|
||||
return (location, size, checksum)
|
||||
return (image_id, size, checksum)
|
||||
|
@ -63,6 +63,11 @@ class TestImagesController(unittest.TestCase):
|
||||
self.assertRaises(webob.exc.HTTPNotFound, self.controller.upload,
|
||||
request, utils.generate_uuid(), 'YYYY')
|
||||
|
||||
def test_upload_data_exists(self):
|
||||
request = test_utils.FakeRequest()
|
||||
self.assertRaises(webob.exc.HTTPConflict, self.controller.upload,
|
||||
request, test_utils.UUID1, 'YYYY')
|
||||
|
||||
|
||||
class TestImageDataDeserializer(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
@ -79,7 +79,7 @@ class TestImagesController(unittest.TestCase):
|
||||
expected = {
|
||||
'name': 'image-2',
|
||||
'owner': test_utils.TENANT1,
|
||||
'location': '1',
|
||||
'location': test_utils.UUID1,
|
||||
'status': 'queued',
|
||||
}
|
||||
self.assertEqual(expected, output)
|
||||
|
Loading…
Reference in New Issue
Block a user