$ python --version
Python 3.6.8
$ pip freeze | grep boto
boto==2.49.0
boto3==1.10.19
botocore==1.13.19
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.
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.
Most helpful comment
Glad to hear that! I will merge it in once I get the tests to pass.