Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: adjusted interfaces and api methods for hub api changes #43

Merged
merged 4 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 40 additions & 18 deletions project/hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,23 @@ class BucketFile(BaseModel):
created_at: datetime
updated_at: datetime

class AnalysisBucket(BaseModel):
id: UUID
type: BucketType
external_id: UUID
analysis_id: UUID
created_at: datetime
updated_at: datetime

class AnalysisFile(BaseModel):
class AnalysisBucketFile(BaseModel):
id: UUID
name: Optional[str]
type: BucketType
root: bool
created_at: datetime
updated_at: datetime
bucket_file_id: UUID
analysis_id: UUID
external_id: UUID
bucket_id: UUID
analysis_id: Optional[UUID]


class ResourceListMeta(BaseModel):
Expand Down Expand Up @@ -241,9 +248,9 @@ def get_bucket_list(self) -> ResourceList[Bucket]:
r.raise_for_status()
return ResourceList[Bucket](**r.json())

def get_bucket_by_id_or_name(self, bucket_id_or_name: str | UUID) -> Bucket | None:
mjugl marked this conversation as resolved.
Show resolved Hide resolved
def get_bucket_by_id(self, bucket_id: str | UUID) -> Bucket | None:
r = httpx.get(
urljoin(self.base_url, f"/storage/buckets/{bucket_id_or_name}"),
urljoin(self.base_url, f"/storage/buckets/{bucket_id}"),
headers=self.auth_client.get_auth_bearer_header(),
)

Expand Down Expand Up @@ -282,37 +289,52 @@ def upload_to_bucket(
r.raise_for_status()
return ResourceList[BucketFile](**r.json())

def get_analysis_file_list(self) -> ResourceList[AnalysisFile]:
def get_analysis_bucket_file_list(self) -> ResourceList[AnalysisBucketFile]:
r = httpx.get(
urljoin(self.base_url, "/analysis-files"),
urljoin(self.base_url, "/analysis-bucket-files"),
headers=self.auth_client.get_auth_bearer_header(),
)

r.raise_for_status()
return ResourceList[AnalysisFile](**r.json())
return ResourceList[AnalysisBucketFile](**r.json())

def get_analysis_bucket(
self,
analysis_id: str | UUID,
type: BucketType
) -> AnalysisBucket:
r = httpx.get(
urljoin(self.base_url, "/analysis-buckets?filter[analysis_id]=" + str(analysis_id) + "&filter[type]=" + str(type)),
headers=self.auth_client.get_auth_bearer_header(),
)

r.raise_for_status()
lst = ResourceList[AnalysisBucket](**r.json())

assert len(lst.data) == 1

return lst.data[0]

def link_bucket_file_to_analysis(
self,
analysis_id: str | UUID,
bucket_file_id: str | UUID,
bucket_id: str | UUID,
external_id: str | UUID,
bucket_file_name: str,
bucket_type: BucketType,
root=True,
) -> AnalysisFile:
) -> AnalysisBucketFile:
r = httpx.post(
urljoin(self.base_url, "/analysis-files"),
urljoin(self.base_url, "/analysis-bucket-files"),
headers=self.auth_client.get_auth_bearer_header(),
json={
"analysis_id": str(analysis_id),
"bucket_file_id": str(bucket_file_id),
"type": bucket_type,
"bucket_id": str(bucket_id),
"external_id": str(external_id),
"name": bucket_file_name,
"root": root,
},
)

r.raise_for_status()
return AnalysisFile(**r.json())
return AnalysisBucketFile(**r.json())

def stream_bucket_file(self, bucket_file_id: str | UUID, chunk_size=1024):
with httpx.stream(
Expand Down
10 changes: 7 additions & 3 deletions project/routers/final.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
get_client_id,
get_api_client,
)
from project.hub import FlameHubClient, format_analysis_bucket_name
from project.hub import FlameHubClient

router = APIRouter()
logger = logging.getLogger(__name__)
Expand All @@ -38,9 +38,13 @@ def __bg_upload_to_remote(
try:
# fetch from local minio
minio_resp = minio.get_object(bucket_name, object_name)

# fetch analysis bucket
analysis_bucket = api.get_analysis_bucket(client_id, "RESULT")

# upload to remote
bucket_file_lst = api.upload_to_bucket(
format_analysis_bucket_name(client_id, "RESULT"),
analysis_bucket.external_id,
object_name,
io.BytesIO(minio_resp.data),
minio_resp.headers.get("Content-Type", "application/octet-stream"),
Expand All @@ -52,7 +56,7 @@ def __bg_upload_to_remote(
bucket_file = bucket_file_lst.data[0]
# link file to analysis
api.link_bucket_file_to_analysis(
client_id, bucket_file.id, bucket_file.name, "RESULT"
client_id, bucket_file.id, bucket_file.name
)
# remove from local minio
minio.remove_object(bucket_name, object_name)
Expand Down
10 changes: 7 additions & 3 deletions project/routers/intermediate.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
get_client_id,
get_api_client,
)
from project.hub import FlameHubClient, format_analysis_bucket_name
from project.hub import FlameHubClient

router = APIRouter()
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -46,8 +46,12 @@ def __bg_upload_to_remote(

try:
minio_resp = minio.get_object(bucket_name, object_name)

# fetch analysis bucket
analysis_bucket = api.get_analysis_bucket(client_id, "TEMP")

bucket_file_lst = api.upload_to_bucket(
format_analysis_bucket_name(client_id, "TEMP"),
analysis_bucket.external_id,
object_name,
io.BytesIO(minio_resp.data),
minio_resp.headers.get("Content-Type", "application/octet-stream"),
Expand All @@ -56,7 +60,7 @@ def __bg_upload_to_remote(
assert len(bucket_file_lst.data) == 1
bucket_file = bucket_file_lst.data[0]
api.link_bucket_file_to_analysis(
client_id, bucket_file.id, bucket_file.name, "TEMP"
analysis_bucket.id, bucket_file.id, bucket_file.name
)
object_id_to_hub_bucket_dict[object_id] = str(bucket_file.id)
minio.remove_object(bucket_name, object_name)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_final.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


def test_200_submit_to_upload(test_client, rng, api_client, analysis_id):
analysis_file_count_old = len(api_client.get_analysis_file_list().data)
analysis_file_count_old = len(api_client.get_analysis_bucket_file_list().data)

blob = next_random_bytes(rng)
r = test_client.put(
Expand All @@ -21,7 +21,7 @@ def test_200_submit_to_upload(test_client, rng, api_client, analysis_id):
assert r.status_code == status.HTTP_204_NO_CONTENT

def __check_analysis_file_count_increases():
analysis_file_count_new = len(api_client.get_analysis_file_list().data)
analysis_file_count_new = len(api_client.get_analysis_bucket_file_list().data)
return analysis_file_count_new > analysis_file_count_old

assert eventually(__check_analysis_file_count_increases)
20 changes: 6 additions & 14 deletions tests/test_hub.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import pytest

from project.hub import (
format_analysis_bucket_name,
BucketType,
)
from tests.common.helpers import next_prefixed_name, eventually, next_random_bytes
Expand All @@ -27,8 +26,8 @@ def result_bucket_name(analysis_id, api_client):
# check that buckets are eventually created (happens asynchronously)
def _check_buckets_exist():
for bucket_type in bucket_types:
bucket_name = format_analysis_bucket_name(analysis_id, bucket_type)
bucket = api_client.get_bucket_by_id_or_name(bucket_name)
analysis_bucket = api_client.get_analysis_bucket(analysis_id, bucket_type)
bucket = api_client.get_bucket_by_id(analysis_bucket.external_id)

if bucket is None:
return False
Expand All @@ -37,15 +36,6 @@ def _check_buckets_exist():

assert eventually(_check_buckets_exist)

# check that buckets are listed correctly
mjugl marked this conversation as resolved.
Show resolved Hide resolved
bucket_list = api_client.get_bucket_list()

for bucket_type in bucket_types:
bucket_name = format_analysis_bucket_name(analysis_id, bucket_type)
assert any([b.name == bucket_name for b in bucket_list.data])

yield format_analysis_bucket_name(analysis_id, "RESULT")


@pytest.fixture
def uploaded_bucket_file(result_bucket_name, api_client, rng):
Expand Down Expand Up @@ -73,16 +63,18 @@ def uploaded_bucket_file(result_bucket_name, api_client, rng):
def test_link_bucket_file_to_analysis(uploaded_bucket_file, analysis_id, api_client):
_, bucket_file = uploaded_bucket_file

analysis_bucket = api_client.get_analysis_bucket(analysis_id, "RESULT")

# check that the analysis file was created
analysis_file = api_client.link_bucket_file_to_analysis(
analysis_id, bucket_file.id, bucket_file.name, bucket_type="RESULT"
analysis_bucket.external_id, bucket_file.id, bucket_file.name
mjugl marked this conversation as resolved.
Show resolved Hide resolved
)

assert analysis_file.name == bucket_file.name
assert analysis_file.bucket_file_id == bucket_file.id

# check that it appears in the list
analysis_file_list = api_client.get_analysis_file_list()
analysis_file_list = api_client.get_analysis_bucket_file_list()
assert any([af.id == analysis_file.id for af in analysis_file_list.data])


Expand Down