Implement HTTP share listing endpoint.

This commit is contained in:
Itamar Turner-Trauring 2022-02-01 10:20:23 -05:00
parent 26f6d0036c
commit c72e7b0585
4 changed files with 72 additions and 8 deletions

View File

@ -630,8 +630,8 @@ Reading
``GET /v1/immutable/:storage_index/shares`` ``GET /v1/immutable/:storage_index/shares``
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Retrieve a list indicating all shares available for the indicated storage index. Retrieve a list (semantically, a set) indicating all shares available for the
For example:: indicated storage index. For example::
[1, 5] [1, 5]

View File

@ -136,6 +136,7 @@ class UploadProgress(object):
""" """
Progress of immutable upload, per the server. Progress of immutable upload, per the server.
""" """
# True when upload has finished. # True when upload has finished.
finished = attr.ib(type=bool) finished = attr.ib(type=bool)
# Remaining ranges to upload. # Remaining ranges to upload.
@ -221,7 +222,7 @@ class StorageClientImmutables(object):
headers=Headers( headers=Headers(
{ {
"content-range": [ "content-range": [
ContentRange("bytes", offset, offset+len(data)).to_header() ContentRange("bytes", offset, offset + len(data)).to_header()
] ]
} }
), ),
@ -268,11 +269,7 @@ class StorageClientImmutables(object):
"GET", "GET",
url, url,
headers=Headers( headers=Headers(
{ {"range": [Range("bytes", [(offset, offset + length)]).to_header()]}
"range": [
Range("bytes", [(offset, offset + length)]).to_header()
]
}
), ),
) )
if response.code == http.PARTIAL_CONTENT: if response.code == http.PARTIAL_CONTENT:
@ -282,3 +279,23 @@ class StorageClientImmutables(object):
raise ClientException( raise ClientException(
response.code, response.code,
) )
@inlineCallbacks
def list_shares(self, storage_index): # type: (bytes,) -> Deferred[Set[int]]
"""
Return the set of shares for a given storage index.
"""
url = self._client._url(
"/v1/immutable/{}/shares".format(_encode_si(storage_index))
)
response = yield self._client._request(
"GET",
url,
)
if response.code == http.OK:
body = yield response.content()
returnValue(set(loads(body)))
else:
raise ClientException(
response.code,
)

View File

@ -255,6 +255,22 @@ class HTTPServer(object):
required.append({"begin": start, "end": end}) required.append({"begin": start, "end": end})
return self._cbor(request, {"required": required}) return self._cbor(request, {"required": required})
@_authorized_route(
_app,
set(),
"/v1/immutable/<string:storage_index>/shares",
methods=["GET"],
)
def list_shares(self, request, authorization, storage_index):
"""
List shares for the given storage index.
"""
storage_index = si_a2b(storage_index.encode("ascii"))
# TODO in future ticket, handle KeyError as 404
share_numbers = list(self._storage_server.get_buckets(storage_index).keys())
return self._cbor(request, share_numbers)
@_authorized_route( @_authorized_route(
_app, _app,
set(), set(),

View File

@ -382,6 +382,37 @@ class ImmutableHTTPAPITests(SyncTestCase):
) )
self.assertEqual(downloaded, expected_data[offset : offset + length]) self.assertEqual(downloaded, expected_data[offset : offset + length])
def test_list_shares(self):
"""
Once a share is finished uploading, it's possible to list it.
"""
im_client = StorageClientImmutables(self.http.client)
upload_secret = urandom(32)
lease_secret = urandom(32)
storage_index = b"".join(bytes([i]) for i in range(16))
result_of(
im_client.create(
storage_index, {1, 2, 3}, 10, upload_secret, lease_secret, lease_secret
)
)
# Initially there are no shares:
self.assertEqual(result_of(im_client.list_shares(storage_index)), set())
# Upload shares 1 and 3:
for share_number in [1, 3]:
progress = result_of(im_client.write_share_chunk(
storage_index,
share_number,
upload_secret,
0,
b"0123456789",
))
self.assertTrue(progress.finished)
# Now shares 1 and 3 exist:
self.assertEqual(result_of(im_client.list_shares(storage_index)), {1, 3})
def test_multiple_shares_uploaded_to_different_place(self): def test_multiple_shares_uploaded_to_different_place(self):
""" """
If a storage index has multiple shares, uploads to different shares are If a storage index has multiple shares, uploads to different shares are