Commit 8a6c8274 authored by Victor's avatar Victor
Browse files

[feature] add and integrate DELETE to blobs server

Add a DELETE method for blobs server and integrate it into client's
BlobManager.
- Resolves: #8846
parent 03617fc9
......@@ -291,6 +291,18 @@ class BlobManager(object):
logger.info("Finished download: (%s, %d)" % (blob_id, size))
defer.returnValue((fd, size))
@defer.inlineCallbacks
def delete(self, blob_id):
logger.info("Staring deletion of blob: %s" % blob_id)
yield self._delete_from_remote(blob_id)
if (yield self.local.exists(blob_id)):
yield self.local.delete(blob_id)
def _delete_from_remote(self, blob_id):
# TODO this needs to be connected in a tube
uri = urljoin(self.remote, self.user + '/' + blob_id)
return self._client.delete(uri)
class SQLiteBlobBackend(object):
......@@ -427,6 +439,11 @@ def testit(reactor):
'get', help='get blob from local db, get if needed')
parser_get.add_argument('blob_id')
# parse delete command
parser_get = subparsers.add_parser(
'delete', help='delete blob from local and remote db')
parser_get.add_argument('blob_id')
# parse list command
parser_get = subparsers.add_parser(
'list', help='list local and remote blob ids')
......@@ -493,6 +510,13 @@ def testit(reactor):
logger.info(":: Result of get: " + fd.getvalue())
logger.info(":: Finished full get: %s" % blob_id)
@defer.inlineCallbacks
def _delete(blob_id):
logger.info(":: Starting deletion of: %s" % blob_id)
manager = _manager()
yield manager.delete(blob_id)
logger.info(":: Finished deletion of: %s" % blob_id)
@defer.inlineCallbacks
def _list():
logger.info(":: Listing local blobs")
......@@ -525,6 +549,8 @@ def testit(reactor):
yield _put(args.blob_id, args.payload)
elif args.action == 'get':
yield _get(args.blob_id)
elif args.action == 'delete':
yield _delete(args.blob_id)
elif args.action == 'list':
yield _list()
elif args.action == 'send_missing':
......
......@@ -157,8 +157,9 @@ class FilesystemBlobsBackend(object):
def get_total_storage(self, user):
return self._get_disk_usage(self._get_path(user))
def delete_blob(user, blob_id):
raise NotImplementedError
def delete_blob(self, user, blob_id):
blob_path = self._get_path(user, blob_id)
os.unlink(blob_path)
def get_blob_size(user, blob_id):
raise NotImplementedError
......@@ -219,6 +220,12 @@ class BlobsResource(resource.Resource):
self._handler.tag_header(user, blob_id, request)
return self._handler.read_blob(user, blob_id, request)
def render_DELETE(self, request):
logger.info("http put: %s" % request.path)
user, blob_id = self._validate(request)
self._handler.delete_blob(user, blob_id)
return ''
def render_PUT(self, request):
logger.info("http put: %s" % request.path)
user, blob_id = self._validate(request)
......
......@@ -130,3 +130,16 @@ class BlobManagerTestCase(unittest.TestCase):
with pytest.raises(BlobAlreadyExistsError):
yield self.manager.put(doc2, len(content))
self.assertFalse(self.manager._encrypt_and_upload.called)
@defer.inlineCallbacks
@pytest.mark.usefixtures("method_tmpdir")
def test_delete_from_local_and_remote(self):
self.manager._encrypt_and_upload = Mock(return_value=None)
self.manager._delete_from_remote = Mock(return_value=None)
content = "Blob content"
doc1 = BlobDoc(BytesIO(content), 'blob_id')
yield self.manager.put(doc1, len(content))
yield self.manager.delete('blob_id')
local_list = yield self.manager.local_list()
self.assertEquals(0, len(local_list))
self.manager._delete_from_remote.assert_called_with('blob_id')
......@@ -120,3 +120,11 @@ class FilesystemBackendTestCase(unittest.TestCase):
yield backend.write_blob('valid', '../../../', DummyRequest(['']))
with pytest.raises(Exception):
yield backend.write_blob('../../../', 'valid', DummyRequest(['']))
@pytest.mark.usefixtures("method_tmpdir")
@mock.patch('leap.soledad.server._blobs.os.unlink')
def test_delete_blob(self, unlink_mock):
backend = _blobs.FilesystemBlobsBackend(self.tempdir)
backend.delete_blob('user', 'blob_id')
unlink_mock.assert_called_once_with(backend._get_path('user',
'blob_id'))
......@@ -100,3 +100,14 @@ class BlobServerTestCase(unittest.TestCase):
result = yield manager.local.get(blob_id)
self.assertIsNotNone(result)
self.assertEquals(result.getvalue(), "X")
@defer.inlineCallbacks
@pytest.mark.usefixtures("method_tmpdir")
def test_upload_then_delete_updates_list(self):
manager = BlobManager('', self.uri, self.secret,
self.secret, 'user')
yield manager._encrypt_and_upload('blob_id1', BytesIO("1"))
yield manager._encrypt_and_upload('blob_id2', BytesIO("2"))
yield manager._delete_from_remote('blob_id1')
blobs_list = yield manager.remote_list()
self.assertEquals(set(['blob_id2']), set(blobs_list))
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment