Moto: can not stop mocking after moto==1.3.14

Created on 17 Nov 2019  路  9Comments  路  Source: spulec/moto

versions

$ python --version
Python 3.6.8
$ pip freeze | grep boto
boto==2.49.0
boto3==1.10.19
botocore==1.13.19

Reporting Bugs

I mock only DynamoDB and run S3 client on real environment. But it has not worked since I update moto to 1.3.14.

Here is a minimum sample code.

import boto3
import moto


if __name__ == '__main__':
    print(moto.__version__)
    mock = moto.mock_dynamodb2()
    mock.start()
    boto3.client('dynamodb')
    mock.stop()
    bucket = boto3.resource('s3').Bucket('test-bucket')
    print(list(bucket.objects.filter(Prefix='dummy')))

Although this code works on moto==1.3.13,

$ AWS_ACCESS_KEY_ID=xxx AWS_SECRET_ACCESS_KEY=xxx AWS_DEFAULT_REGION=xxx python main.py 
1.3.13
[s3.ObjectSummary(bucket_name='test-bucket', key='dummy')]

does not work on moto==1.3.14.

$ AWS_ACCESS_KEY_ID=xxx AWS_SECRET_ACCESS_KEY=xxx AWS_DEFAULT_REGION=xxx python main.py 
1.3.14
Traceback (most recent call last):
  File "main.py", line 12, in <module>
    print(list(bucket.objects.filter(Prefix='dummy')))
  File "/home/nakagawa/.pyenv/versions/3.6.8/lib/python3.6/site-packages/boto3/resources/collection.py", line 83, in __iter__
    for page in self.pages():
  File "/home/nakagawa/.pyenv/versions/3.6.8/lib/python3.6/site-packages/boto3/resources/collection.py", line 166, in pages
    for page in pages:
  File "/home/nakagawa/.pyenv/versions/3.6.8/lib/python3.6/site-packages/botocore/paginate.py", line 255, in __iter__
    response = self._make_request(current_kwargs)
  File "/home/nakagawa/.pyenv/versions/3.6.8/lib/python3.6/site-packages/botocore/paginate.py", line 332, in _make_request
    return self._method(**current_kwargs)
  File "/home/nakagawa/.pyenv/versions/3.6.8/lib/python3.6/site-packages/botocore/client.py", line 357, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/home/nakagawa/.pyenv/versions/3.6.8/lib/python3.6/site-packages/botocore/client.py", line 661, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (InvalidAccessKeyId) when calling the ListObjects operation: The AWS Access Key Id you provided does not exist in our records.
bug

Most helpful comment

Glad to hear that! I will merge it in once I get the tests to pass.

All 9 comments

What happens when you use the Context Manager: https://github.com/spulec/moto#context-manager ?

You mean using Context Manager like following?

import boto3
import moto


if __name__ == '__main__':
    print(moto.__version__)
    with moto.mock_dynamodb2():
        boto3.client('dynamodb')
    bucket = boto3.resource('s3').Bucket('test-bucket')
    print(list(bucket.objects.filter(Prefix='dummy')))

It does not work as well.

$ AWS_ACCESS_KEY_ID=xxx AWS_SECRET_ACCESS_KEY=xxx AWS_DEFAULT_REGION=xxx python main.py 
1.3.14
Traceback (most recent call last):
  File "main.py", line 10, in <module>
    print(list(bucket.objects.filter(Prefix='dummy')))
  File "/home/nakagawa/.pyenv/versions/3.6.8/lib/python3.6/site-packages/boto3/resources/collection.py", line 83, in __iter__
    for page in self.pages():
  File "/home/nakagawa/.pyenv/versions/3.6.8/lib/python3.6/site-packages/boto3/resources/collection.py", line 166, in pages
    for page in pages:
  File "/home/nakagawa/.pyenv/versions/3.6.8/lib/python3.6/site-packages/botocore/paginate.py", line 255, in __iter__
    response = self._make_request(current_kwargs)
  File "/home/nakagawa/.pyenv/versions/3.6.8/lib/python3.6/site-packages/botocore/paginate.py", line 332, in _make_request
    return self._method(**current_kwargs)
  File "/home/nakagawa/.pyenv/versions/3.6.8/lib/python3.6/site-packages/botocore/client.py", line 357, in _api_call
    return self._make_api_call(operation_name, kwargs)
  File "/home/nakagawa/.pyenv/versions/3.6.8/lib/python3.6/site-packages/botocore/client.py", line 661, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (InvalidAccessKeyId) when calling the ListObjects operation: The AWS Access Key Id you provided does not exist in our records.

Well that's no good :(

Hmm... while doing some debugging, I found that in botocore's credentials.py, the access_key and secret_key are set to foobar_key, and foobar_secret, respectively.

For some reason, the .stop() function is not unsetting the FAKE_KEYS:

    def start(self, reset=True):
        self.env_variables_mocks.start()

        self.__class__.nested_count += 1
        if reset:
            for backend in self.backends.values():
                backend.reset()

        self.enable_patching()

    def stop(self):
        self.env_variables_mocks.stop()
        self.__class__.nested_count -= 1

        if self.__class__.nested_count < 0:
            raise RuntimeError("Called stop() before start().")

        if self.__class__.nested_count == 0:
            self.disable_patching()

I have a hunch that what we need to do is mock the boto3 DEFAULT_SESSION so that it is None after the the mocks stop.

It appears that:

    def _register_credential_provider(self):
        self._components.lazy_register_component(
            'credential_provider',
            lambda:  botocore.credentials.create_credential_resolver(self))

... is being cached and used after the mock has ended.

Preliminary PR for fixing this is in #2578.

Will need to do more testing. Feel free to pip install from my repo branch and test that it works for you.

Thank you! It works fine after $ pip install git+https://github.com/mikegrima/moto.git@fixunmock.

Glad to hear that! I will merge it in once I get the tests to pass.

Was this page helpful?
0 / 5 - 0 ratings