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

MD5 Check Sum generate and check #508

Merged
merged 9 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Brewtils Changelog
------
TBD

- Apply MD5 Check Sum of chunked files to ensure files are loaded into memory properly
- Updated Plugin `max_concurrent` to support -1 to utilize the default formula that `concurrent.futures.ThreadPoolExecutor` supports `min(32, os.cpu_count() + 4)`
- Updated SystemClient to utilize the local Garden name for default Namespace if none can be determined

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ clean: clean-build clean-docs clean-python clean-test ## remove everything but s

# Formatting
format: ## Run black formatter in-line
black --target-version py27 $(MODULE_NAME) $(TEST_DIR)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow

black $(MODULE_NAME) $(TEST_DIR)


# Linting
Expand Down
4 changes: 4 additions & 0 deletions brewtils/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,7 @@ def __init__(
owner=None,
job=None,
request=None,
md5_sum=None,
):
self.id = id
self.owner_id = owner_id
Expand All @@ -532,6 +533,7 @@ def __init__(
self.file_size = file_size
self.chunks = chunks
self.chunk_size = chunk_size
self.md5_sum = md5_sum

def __str__(self):
return self.file_name
Expand Down Expand Up @@ -593,6 +595,7 @@ def __init__(
chunks_ok=None,
operation_complete=None,
message=None,
md5_sum=None,
):
# Top-level file info
self.file_id = file_id
Expand All @@ -603,6 +606,7 @@ def __init__(
self.chunks = chunks
self.owner_id = owner_id
self.owner_type = owner_type
self.md5_sum = md5_sum
# Chunk info
self.chunk_id = chunk_id
self.offset = offset
Expand Down
12 changes: 12 additions & 0 deletions brewtils/rest/easy_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from io import BytesIO
from pathlib import Path
from typing import Any, Callable, List, NoReturn, Optional, Type, Union
from hashlib import md5

import six
import wrapt
Expand Down Expand Up @@ -999,6 +1000,8 @@ def upload_chunked_file(
fd = file_to_upload
require_close = False

default_file_params["md5_sum"] = md5(fd.getbuffer()).hexdigest()

try:
default_file_params["file_name"] = desired_filename or fd.name
except AttributeError:
Expand Down Expand Up @@ -1066,6 +1069,15 @@ def download_chunked_file(self, file_id):

file_obj.seek(0)

if (
"md5_sum" in meta
and meta["md5_sum"] != md5(file_obj.getbuffer()).hexdigest()
):
raise ValidationError(
"Requested file %s MD5 SUM %s does match actual MD5 SUM %s"
% (file_id, meta["md5_sum"], md5(file_obj.getbuffer()).hexdigest())
)

return file_obj

def delete_chunked_file(self, file_id):
Expand Down
2 changes: 2 additions & 0 deletions brewtils/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ class FileSchema(BaseSchema):
file_size = fields.Int(allow_none=False)
chunks = fields.Dict(allow_none=True)
chunk_size = fields.Int(allow_none=False)
md5_sum = fields.Str(allow_none=True)


class FileChunkSchema(BaseSchema):
Expand All @@ -281,6 +282,7 @@ class FileStatusSchema(BaseSchema):
chunks = fields.Dict(allow_none=True)
owner_id = fields.Str(allow_none=True)
owner_type = fields.Str(allow_none=True)
md5_sum = fields.Str(allow_none=True)
# Chunk info
chunk_id = fields.Str(allow_none=True)
offset = fields.Int(allow_none=True)
Expand Down
7 changes: 7 additions & 0 deletions test/rest/easy_client_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def target_file():
fp.tell = Mock(return_value=0)
fp.seek = Mock(return_value=1024)
fp.read = Mock(side_effect=iter([b"content", None]))
fp.getbuffer = Mock(return_value=b"content")
return fp


Expand Down Expand Up @@ -596,6 +597,12 @@ def test_upload_chunked_file(
client._check_chunked_file_validity = Mock(return_value=(True, {}))

resolvable = client.upload_chunked_file(target_file, "desired_name")
_, called_kwargs = rest_client.post_chunked_file.call_args[0]

assert called_kwargs["md5_sum"] == "9a0364b9e99bb480dd25e1f0284c8555"
assert called_kwargs["file_name"] == "desired_name"
assert called_kwargs["file_size"] == 1024
assert called_kwargs["chunk_size"] == 261120
assert resolvable == bg_resolvable_chunk

def test_upload_file_fail(self, client, rest_client, server_error, target_file):
Expand Down
Loading