Thanks to visit codestin.com
Credit goes to github.com

Skip to content

S3 asf fixes detected by Terraform test suite #7027

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

Merged
merged 11 commits into from
Oct 21, 2022
Merged

S3 asf fixes detected by Terraform test suite #7027

merged 11 commits into from
Oct 21, 2022

Conversation

steffyP
Copy link
Member

@steffyP steffyP commented Oct 14, 2022

This PR contains several fixes for S3 ASF that were detected by the terraform test suite:

  • Website Hosting: fix handling for empty ReplaceKeyPrefixWith for redirect-routing rule (in that case it should remove the the KeyPrefixEquals from the original url and then do the redirect)
  • Bucket name with slashes: fix parsing issue; preserve name for keys that end with slash
  • Patch to change casing of content-lanugage , content-disposition and cache-control to be picked up by parser
  • Patch for bucket-key-enbled header x-amz-server-side-encryption-bucket-key-enabled which is returned as camel-case by moto, but should be lowercase to be picked up by the parser
  • fix resetting of content-length for HEAD requests that are forwarded using the Proxy for vhost-style requests.
  • fix issues with delete-objects:
    • query parameter was added twice to the url for vhost-style forwarding
    • add moto-patch to include old fix from legacy s3 provider
    • remove trailing = from the path (/<bucket>/?delete= but expects /<bucket>/?delete)
    • add notifications for delete-objects
    • implement quiet mode for delete-objects
  • fix bucket replication and added tests
  • add spec-patch for log-delivery-write, which was missing from the BucketCannedACL

TODO before merge:

  • remove last commit, which excludes some cors-related tests, that were timing out (CORS not yet implemented)
  • rebase with master (remove ASF enabled by default)

@steffyP steffyP temporarily deployed to localstack-ext-tests October 14, 2022 17:20 Inactive
@@ -48,6 +48,8 @@
ObjectCannedACL.bucket_owner_read,
ObjectCannedACL.public_read,
ObjectCannedACL.public_read_write,
# according to docs 'log-delivery-write' is also valid https://docs.aws.amazon.com/AmazonS3/latest/userguide/acl-overview.html#canned-acl
"log-delivery-write", # TODO add to parser? seems to be missing accross services though
Copy link
Contributor

Choose a reason for hiding this comment

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

We could add it with a patch I guess, weird it's not part of it.

@github-actions
Copy link

github-actions bot commented Oct 14, 2022

LocalStack integration with Pro

       3 files  ±0         3 suites  ±0   1h 20m 18s ⏱️ - 1m 34s
1 417 tests +7  1 229 ✔️ +2  188 💤 +5  0 ±0 
2 015 runs  +7  1 595 ✔️ +2  420 💤 +5  0 ±0 

Results for commit 8917042. ± Comparison against base commit 93e2bbe.

♻️ This comment has been updated with latest results.

@steffyP steffyP temporarily deployed to localstack-ext-tests October 17, 2022 18:21 Inactive
@steffyP steffyP temporarily deployed to localstack-ext-tests October 18, 2022 11:19 Inactive
@steffyP steffyP temporarily deployed to localstack-ext-tests October 19, 2022 09:01 Inactive
@steffyP steffyP temporarily deployed to localstack-ext-tests October 19, 2022 10:46 Inactive
@steffyP steffyP temporarily deployed to localstack-ext-tests October 19, 2022 13:53 Inactive
@steffyP steffyP temporarily deployed to localstack-ext-tests October 20, 2022 07:50 Inactive
@steffyP steffyP temporarily deployed to localstack-ext-tests October 20, 2022 09:21 Inactive
@steffyP steffyP marked this pull request as ready for review October 20, 2022 10:00
Copy link
Member

@thrau thrau left a comment

Choose a reason for hiding this comment

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

LGTM! i don't have a good suggestion on how to get the s3 hack out of the parser right now, so i'd be OK with merging it for now with the FIXME. i'll let alex make the final call though.

if (
self.service.service_name == "s3"
and uri_param_name == "Key"
and request.url.split("?")[0].endswith(f"{uri_params[uri_param_name]}/")
Copy link
Member

Choose a reason for hiding this comment

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

base_url: "Like url but without the query string."

Suggested change
and request.url.split("?")[0].endswith(f"{uri_params[uri_param_name]}/")
and request.base_url.endswith(f"{uri_params[uri_param_name]}/")

Comment on lines 251 to 257
# FIXME special case for s3 object-names (=key): trailing '/' are valid and need to be preserved
# however, the url-matcher removes it from the key
# we check the request.url to verify the name
if (
self.service.service_name == "s3"
and uri_param_name == "Key"
and request.url.split("?")[0].endswith(f"{uri_params[uri_param_name]}/")
Copy link
Member

Choose a reason for hiding this comment

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

predictably i'd prefer encapsulating this in the s3 parser somehow :D i don't have a good suggestion at the moment, will take a look after the review, maybe @alexrashed also has some ideas

Copy link
Member

Choose a reason for hiding this comment

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

To be host, the service_name is something we desperately tried to avoid in these "generalized" parsers.
Since there is already an S3RequestParser, we could check this case and modifying the uri_params and afterwards calling the super method. Something like this:

class S3RequestParser(RestXMLRequestParser):
    def _parse_shape(
        self, request: HttpRequest, shape: Shape, node: Any, uri_params: Mapping[str, Any] = None
    ) -> Any:
        if shape is not None and uri_params is not None \
                and shape.serialization.get("location") == "uri" \
                and shape.serialization.get("name") == "Key" \
                and request.url.split("?")[0].endswith(f"{uri_params['Key']}/"):
            uri_params = dict(uri_params)
            uri_params["Key"] = uri_params["Key"] + "/"
        return super()._parse_shape(request, shape, node, uri_params)

Another option would be to externalize the location parsing to a separate function, but this doesn't seem to be worth the effort / complexity.

I'm happy to assist if I can be of service!

Comment on lines +51 to +54
if request.method == "HEAD":
# for head we have to keep the original content-length, but it will be re-calcualated when creating
# the final_response object
final_response.content_length = response.headers.get("Content-Length", 0)
Copy link
Member

Choose a reason for hiding this comment

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

good catch!

Copy link
Member

@alexrashed alexrashed left a comment

Choose a reason for hiding this comment

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

Wow! This is great! The S3 ASF migration really goes to the limits (and beyond) of ASF. 🚀
It would be nice if we could externalize the S3 specific edge case in the parser, but this also shouldn't be a blocker (I could also take care of that another time).

Comment on lines 251 to 257
# FIXME special case for s3 object-names (=key): trailing '/' are valid and need to be preserved
# however, the url-matcher removes it from the key
# we check the request.url to verify the name
if (
self.service.service_name == "s3"
and uri_param_name == "Key"
and request.url.split("?")[0].endswith(f"{uri_params[uri_param_name]}/")
Copy link
Member

Choose a reason for hiding this comment

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

To be host, the service_name is something we desperately tried to avoid in these "generalized" parsers.
Since there is already an S3RequestParser, we could check this case and modifying the uri_params and afterwards calling the super method. Something like this:

class S3RequestParser(RestXMLRequestParser):
    def _parse_shape(
        self, request: HttpRequest, shape: Shape, node: Any, uri_params: Mapping[str, Any] = None
    ) -> Any:
        if shape is not None and uri_params is not None \
                and shape.serialization.get("location") == "uri" \
                and shape.serialization.get("name") == "Key" \
                and request.url.split("?")[0].endswith(f"{uri_params['Key']}/"):
            uri_params = dict(uri_params)
            uri_params["Key"] = uri_params["Key"] + "/"
        return super()._parse_shape(request, shape, node, uri_params)

Another option would be to externalize the location parsing to a separate function, but this doesn't seem to be worth the effort / complexity.

I'm happy to assist if I can be of service!

@steffyP steffyP temporarily deployed to localstack-ext-tests October 21, 2022 13:22 Inactive
@steffyP
Copy link
Member Author

steffyP commented Oct 21, 2022

Moved the specific s3-parsing (for the special case with trailing "/" in the key name) to the S3RequestParser as suggested by @alexrashed (thank you! 🙂)

Removing the commit with the excluded CORS tests and rebasing with master now (to check that the tests still work with the old s3 provider), before merging.

@steffyP steffyP temporarily deployed to localstack-ext-tests October 21, 2022 14:16 Inactive
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.06%) to 79.269% when pulling 8917042 on s3-asf-fixes into 93e2bbe on master.

@steffyP steffyP merged commit 1bbc076 into master Oct 21, 2022
@steffyP steffyP deleted the s3-asf-fixes branch October 21, 2022 15:42
cmoralesmx pushed a commit to cmoralesmx/localstack that referenced this pull request Oct 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants