sample-serverless-image-resizer-s3-lambda icon indicating copy to clipboard operation
sample-serverless-image-resizer-s3-lambda copied to clipboard

Resizer might be broken

Open Mo0rBy opened this issue 1 year ago • 3 comments

Hello,

I came across this when trying to test out LocalStack and what it can do.

I clone this repo and deployed the application using the bin/deploy.sh and it all looked good, I could access the website URL and it looked to be all good.

I ran the tests and get the following output:

============================= test session starts ==============================
platform darwin -- Python 3.11.6, pytest-8.3.2, pluggy-1.5.0 -- /Users/wmoorby/.pyenv/versions/3.11.6/bin/python3.11
cachedir: .pytest_cache
rootdir: /Users/wmoorby/Library/CloudStorage/OneDrive(O365)/sample-serverless-image-resizer-s3-lambda
collecting ... collected 2 items

tests/test_integration.py::test_s3_resize_integration FAILED             [ 50%]
tests/test_integration.py::test_failure_sns_to_ses_integration PASSED    [100%]

=================================== FAILURES ===================================
__________________________ test_s3_resize_integration __________________________

    def test_s3_resize_integration():
        file = os.path.join(os.path.dirname(__file__), "nyan-cat.png")
        key = os.path.basename(file)
    
        parameter = ssm.get_parameter(Name="/localstack-thumbnail-app/buckets/images")
        source_bucket = parameter["Parameter"]["Value"]
    
        parameter = ssm.get_parameter(Name="/localstack-thumbnail-app/buckets/resized")
        target_bucket = parameter["Parameter"]["Value"]
    
        s3.upload_file(file, Bucket=source_bucket, Key=key)
    
        # wait for the resized image to appear
>       s3.get_waiter("object_exists").wait(Bucket=target_bucket, Key=key)

tests/test_integration.py:51: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/Users/wmoorby/.pyenv/versions/3.11.6/lib/python3.11/site-packages/botocore/waiter.py:55: in wait
    Waiter.wait(self, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <botocore.waiter.S3.Waiter.ObjectExists object at 0x103421b10>
kwargs = {'Bucket': 'localstack-thumbnails-app-resized', 'Key': 'nyan-cat.png'}
acceptors = [<botocore.waiter.AcceptorConfig object at 0x103421bd0>, <botocore.waiter.AcceptorConfig object at 0x103423110>]
current_state = 'retry', config = {}, sleep_amount = 5, max_attempts = 20
last_matched_acceptor = <botocore.waiter.AcceptorConfig object at 0x103423110>
num_attempts = 20

    def wait(self, **kwargs):
        acceptors = list(self.config.acceptors)
        current_state = 'waiting'
        # pop the invocation specific config
        config = kwargs.pop('WaiterConfig', {})
        sleep_amount = config.get('Delay', self.config.delay)
        max_attempts = config.get('MaxAttempts', self.config.max_attempts)
        last_matched_acceptor = None
        num_attempts = 0
    
        while True:
            response = self._operation_method(**kwargs)
            num_attempts += 1
            for acceptor in acceptors:
                if acceptor.matcher_func(response):
                    last_matched_acceptor = acceptor
                    current_state = acceptor.state
                    break
            else:
                # If none of the acceptors matched, we should
                # transition to the failure state if an error
                # response was received.
                if is_valid_waiter_error(response):
                    # Transition to a failure state, which we
                    # can just handle here by raising an exception.
                    raise WaiterError(
                        name=self.name,
                        reason='An error occurred ({}): {}'.format(
                            response['Error'].get('Code', 'Unknown'),
                            response['Error'].get('Message', 'Unknown'),
                        ),
                        last_response=response,
                    )
            if current_state == 'success':
                logger.debug(
                    "Waiting complete, waiter matched the " "success state."
                )
                return
            if current_state == 'failure':
                reason = f'Waiter encountered a terminal failure state: {acceptor.explanation}'
                raise WaiterError(
                    name=self.name,
                    reason=reason,
                    last_response=response,
                )
            if num_attempts >= max_attempts:
                if last_matched_acceptor is None:
                    reason = 'Max attempts exceeded'
                else:
                    reason = (
                        f'Max attempts exceeded. Previously accepted state: '
                        f'{acceptor.explanation}'
                    )
>               raise WaiterError(
                    name=self.name,
                    reason=reason,
                    last_response=response,
                )
E               botocore.exceptions.WaiterError: Waiter ObjectExists failed: Max attempts exceeded. Previously accepted state: Matched expected HTTP status code: 404

/Users/wmoorby/.pyenv/versions/3.11.6/lib/python3.11/site-packages/botocore/waiter.py:387: WaiterError
=========================== short test summary info ============================
FAILED tests/test_integration.py::test_s3_resize_integration - botocore.excep...
==================== 1 failed, 1 passed in 96.89s (0:01:36) ====================

I double checked the website I was running + the video in this repo, and it looks like the resizing part actually doesn't work. I noticed this as there was no resize number of bytes when attempting to resize an image in the UI.

Here is a screenshot of my hosted application: Screenshot 2024-09-03 at 16 16 46

And here it is from the video in this repo: Screenshot 2024-09-03 at 16 18 18

I'm not really sure if this is an actual error within the python resizing script or if there is something wrong with my setup (I don't know what would be, I just cloned the repo and ran the included deploy script).

Mo0rBy avatar Sep 03 '24 15:09 Mo0rBy

@Mo0rBy, Have you found any error while running the deployment script?

abidkhan484 avatar Nov 29 '24 04:11 abidkhan484

@abidkhan484 I don't know where the error is exactly. Been a while since I've looked at this now but from what I remember, there were no errors or issues when deploying this, I just saw that 1 of the pytest tests was failing. Initially I thought that it must be the test that was broken as this is a nice and simple setup that probably was created and then never touched again due to the fact that it's a tutorial repo.

So I looked at the test code and then realised with the screenshots above, the actual webapp page doesn't work in the way that it should.

So like I said, don't know exactly where the issue is occurring, but I believe it's related to the actual deployment of the resources, not the test that needs updating.

Mo0rBy avatar Dec 05 '24 10:12 Mo0rBy

@Mo0rBy When running the deployment/awslocal/deploy.sh script, I encountered the following error:

ERROR: Could not find a version that satisfies the requirement Pillow==9.2.0 (from versions: 10.0.0, 10.0.1, 10.1.0, 10.2.0, 10.3.0, 10.4.0, 11.0.0, 11.1.0)
ERROR: No matching distribution found for Pillow==9.2.0

This issue causes the resize Lambda to malfunction, and any uploaded image does not generate a preview. Additionally, the tests fail.

I was able to resolve the issue by upgrading the version of Pillow to 10.0.0 in the requirements.txt file for the resize Lambda function. Here’s the change I made:

Fix:

# ./lambdas/resize/requirements.txt
Pillow==10.0.0

After making this change, the resize Lambda worked as expected, image previews were generated correctly, and the tests passed successfully.

I hope this helps resolve the issue.

Lucho00Cuba avatar Feb 23 '25 17:02 Lucho00Cuba

This issue has been fixed

blkgrlcto avatar Sep 11 '25 15:09 blkgrlcto