-
Notifications
You must be signed in to change notification settings - Fork 165
Fix ArtifactFileField.pre_save spurious rejection when MEDIA_ROOT is empty #8076
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
base: main
Are you sure you want to change the base?
Changes from all commits
f2b0db0
b650deb
36931f7
99acb00
1ceb90d
61a63c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Fixed ``ArtifactFileField.pre_save`` spuriously rejecting artifact uploads whose filenames start with ``artifact`` when ``MEDIA_ROOT`` is empty (S3/Azure object-storage backends). The ``startswith`` guard now short-circuits when ``MEDIA_ROOT`` is empty, preventing false detection of fresh uploads as already-stored artifacts. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -70,7 +70,12 @@ def pre_save(self, model_instance, add): | |
| artifact_storage_path, | ||
| os.path.join(settings.MEDIA_ROOT, artifact_storage_path), | ||
| ] | ||
| is_in_artifact_storage = file.name.startswith(os.path.join(settings.MEDIA_ROOT, "artifact")) | ||
| # Guard against empty MEDIA_ROOT (object-storage backends such as S3/Azure set it to ""), | ||
| # where os.path.join("", "artifact") == "artifact" and any filename starting with | ||
| # "artifact" would be falsely detected as already residing in artifact storage. | ||
| is_in_artifact_storage = bool(settings.MEDIA_ROOT) and file.name.startswith( | ||
| os.path.join(settings.MEDIA_ROOT, "artifact") | ||
| ) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is short-circuiting actually what we want here? |
||
|
|
||
| if not already_in_place and is_in_artifact_storage: | ||
| raise ValueError( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| """ | ||
| Regression test for https://github.com/pulp/pulpcore/issues/8041 | ||
|
|
||
| ``ArtifactFileField.pre_save`` used a raw ``startswith`` against ``settings.MEDIA_ROOT`` | ||
| to detect files already in artifact storage. When ``MEDIA_ROOT`` is ``""`` | ||
| (S3/Azure object-storage backends), ``os.path.join("", "artifact") == "artifact"``, | ||
| so any upload whose filename started with ``"artifact"`` was falsely detected as | ||
| already-stored and raised ``ValueError`` → HTTP 500. | ||
| """ | ||
|
|
||
| import os | ||
|
|
||
| import pytest | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| "filename", | ||
| [ | ||
| "artifact-foo-1.0-1.noarch.rpm", | ||
| "artifact-bar.tar.gz", | ||
| ], | ||
| ) | ||
| def test_artifact_upload_artifact_prefix_filename_when_media_root_empty( | ||
| pulpcore_bindings, tmp_path, pulp_settings, filename | ||
| ): | ||
| """Upload a file whose name starts with ``artifact`` — must succeed on object-storage backends. | ||
|
|
||
| This test only applies when ``MEDIA_ROOT`` is empty (object-storage backends such | ||
| as S3 and Azure). On filesystem backends the bug does not occur, so the test is | ||
| skipped to avoid false positives. | ||
| """ | ||
| if pulp_settings.MEDIA_ROOT: | ||
| pytest.skip("Bug GH-8041 only affects backends where MEDIA_ROOT is empty (S3/Azure).") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It definitely shouldn't be in a file named I'm not sure I like having it so narrowly scoped either. TBH for such a specific bug we probably do not need a regression test, but more testing in general would be welcome if there are gaps. |
||
|
|
||
| temp_file = tmp_path / filename | ||
| temp_file.write_bytes(os.urandom(32)) | ||
|
|
||
| # Before the fix this raised HTTP 500 (ValueError in ArtifactFileField.pre_save). | ||
| artifact = pulpcore_bindings.ArtifactsApi.create(str(temp_file)) | ||
| assert artifact.pulp_href is not None | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
attack of the double backticks