Add If-Match and If-None-Match support for PutObject operations#893
Conversation
cf58a59 to
9dc6d74
Compare
9dc6d74 to
c67b7b9
Compare
gaul
left a comment
There was a problem hiding this comment.
This looks good, please address comments so I can merge and I'll run a new release afterwards.
| "non-existent", BYTE_SOURCE.openStream(), metadata); | ||
| nonExistentRequest.setIfNoneMatch("*"); | ||
| client.putObject(nonExistentRequest); | ||
| } |
There was a problem hiding this comment.
Can you enable some s3-tests, specifically removing @pytest.mark.fails_on_s3proxy for test_put_object_ifmatch_failed, test_put_object_ifmatch_nonexisted_failed? I think then you can remove these duplicated tests.
There was a problem hiding this comment.
Sure, I didn't even notice the python tests. I removed the Java tests and created a PR gaul/s3-tests#3 that enables the mentioned tests as well as the following two tests which are now covered:
test_put_object_ifnonmatch_failedtest_put_object_ifnonmatch_overwrite_existed_failed
The python tests are completing successfully now.
================ 242 passed, 104 skipped, 561 deselected, 3 warnings in 29.08s =================
py311: OK (32.88=setup[3.52]+cmd[29.37] seconds)
congratulations :) (32.90 seconds)
| String ifNoneMatch = request.getHeader(HttpHeaders.IF_NONE_MATCH); | ||
|
|
||
| if (ifMatch != null || ifNoneMatch != null) { | ||
| BlobMetadata metadata = blobStore.blobMetadata(containerName, |
There was a problem hiding this comment.
Can you add a TODO: that this is an emulated operation and therefore not atomic? Also please add to the README under "S3Proxy emulates the following operations":
- conditional PUT object
The long-term plan is to migrate off of jclouds which lacks support to SDKs that do but in the near-term we could add a BlobStore2 class that calls to the Azure (and someday AWS) SDK then falls back to emulation for jclouds blobstores.
|
Please investigate the s3-tests failures. You can run these locally via |
|
The tests worked fine for the transient-nio2 provider and only occured for the azurite storage. The issue was that the AzureBlobStore implementation did not follow jclouds BlobStore interface and threw the undocumented KeyNotFoundException instead of returning null when an object doesn't exist. The interface states that null should be returned in that case and the transient-nio2 provider implements it properly. Thats why those tests worked. I fixed the AzureBlobStore implementation to handle that case and match the interface. FYI when Maven uses Java 24 instead of Java 11 the @autoservice annotation processor breaks and doesn't generate the required service registration files. This leads to the azureblob-sdk provider not being found. |
gaul
left a comment
There was a problem hiding this comment.
FYI when Maven uses Java 24 instead of Java 11 the https://github.com/autoservice annotation processor breaks and doesn't generate the required service registration files. This leads to the azureblob-sdk provider not being found.
Can you explain how to reproduce these symptoms, preferably in an issue?
| } catch (BlobStorageException bse) { | ||
| if (bse.getErrorCode().equals(BlobErrorCode.BLOB_NOT_FOUND)) { | ||
| return null; | ||
| } |
There was a problem hiding this comment.
Thanks for fixing this! I believe that this only affected internal-only calls like the MPU ones and handleBlobMetadata coincidentally worked due to the top-level handling KeyNotFoundException.
There was a problem hiding this comment.
Sure, I'll make a note and will reproduce it to create an issue tomorrow. It's quite late here already. Thanks for saving me the trouble to maintain a minio instance on Azure 🙂
|
Thank you for your contribution @klaudworks! |
This PR implements If-Match and If-None-Match functionality for PutObject requests. A feature added by AWS last year. It addresses #831 and #732 as well as my own requirements that prevent me from using s3proxy in its current state.
I followed the S3 API specification for conditional headers:
I checked the AWS docs to match the HTTP status codes: https://docs.aws.amazon.com/AmazonS3/latest/userguide/conditional-writes.html. See the old and new behavior in the manual test results table.
Workarounds
Unlike for getBlobs, the jcloud libary was missing the functionality to specify ifMatch and ifNoneMatch for putBlobs. Therefore, I have to check and verify the ETag myself.
Manual Test Results
Automated tests can be seen in the diff. I also tested the changes manually by building and spinning up the s3proxy as a docker container and using an Azure storage account as the backend:
I tested both the old and the new code manually: