Skip to content

Commit 78a0faf

Browse files
Use model's AWS credentials in threads (pynamodb#1160)
When a model specifies custom AWS credentials (instead of global ones), they should be used when creating new sessions in threads. Previously, threads would always use the global credentials.
1 parent 6677633 commit 78a0faf

File tree

3 files changed

+28
-8
lines changed

3 files changed

+28
-8
lines changed

pynamodb/connection/base.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,10 @@ def __init__(self,
257257
max_retry_attempts: Optional[int] = None,
258258
base_backoff_ms: Optional[int] = None,
259259
max_pool_connections: Optional[int] = None,
260-
extra_headers: Optional[Mapping[str, str]] = None):
260+
extra_headers: Optional[Mapping[str, str]] = None,
261+
aws_access_key_id: Optional[str] = None,
262+
aws_secret_access_key: Optional[str] = None,
263+
aws_session_token: Optional[str] = None):
261264
self._tables: Dict[str, MetaTable] = {}
262265
self.host = host
263266
self._local = local()
@@ -298,6 +301,10 @@ def __init__(self,
298301
else:
299302
self._extra_headers = get_settings_value('extra_headers')
300303

304+
self._aws_access_key_id = aws_access_key_id
305+
self._aws_secret_access_key = aws_secret_access_key
306+
self._aws_session_token = aws_session_token
307+
301308
def __repr__(self) -> str:
302309
return "Connection<{}>".format(self.client.meta.endpoint_url)
303310

@@ -558,6 +565,10 @@ def session(self) -> botocore.session.Session:
558565
# botocore client creation is not thread safe as of v1.2.5+ (see issue #153)
559566
if getattr(self._local, 'session', None) is None:
560567
self._local.session = get_session()
568+
if self._aws_access_key_id and self._aws_secret_access_key:
569+
self._local.session.set_credentials(self._aws_access_key_id,
570+
self._aws_secret_access_key,
571+
self._aws_session_token)
561572
return self._local.session
562573

563574
@property

pynamodb/connection/table.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,14 @@ def __init__(
4141
max_retry_attempts=max_retry_attempts,
4242
base_backoff_ms=base_backoff_ms,
4343
max_pool_connections=max_pool_connections,
44-
extra_headers=extra_headers)
44+
extra_headers=extra_headers,
45+
aws_access_key_id=aws_access_key_id,
46+
aws_secret_access_key=aws_secret_access_key,
47+
aws_session_token=aws_session_token)
48+
4549
if meta_table is not None:
4650
self.connection.add_meta_table(meta_table)
4751

48-
if aws_access_key_id and aws_secret_access_key:
49-
self.connection.session.set_credentials(aws_access_key_id,
50-
aws_secret_access_key,
51-
aws_session_token)
52-
5352
def get_meta_table(self) -> MetaTable:
5453
"""
5554
Returns a MetaTable

tests/test_table_connection.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Test suite for the table class
33
"""
44
from unittest import TestCase
5+
from concurrent.futures import ThreadPoolExecutor
56

67
from pynamodb.connection import TableConnection
78
from pynamodb.connection.base import MetaTable
@@ -38,7 +39,16 @@ def test_connection_session_set_credentials(self):
3839
aws_access_key_id='access_key_id',
3940
aws_secret_access_key='secret_access_key')
4041

41-
credentials = conn.connection.session.get_credentials()
42+
def get_credentials():
43+
return conn.connection.session.get_credentials()
44+
45+
credentials = get_credentials()
46+
self.assertEqual(credentials.access_key, 'access_key_id')
47+
self.assertEqual(credentials.secret_key, 'secret_access_key')
48+
49+
with ThreadPoolExecutor() as executor:
50+
fut = executor.submit(get_credentials)
51+
credentials = fut.result()
4252

4353
self.assertEqual(credentials.access_key, 'access_key_id')
4454
self.assertEqual(credentials.secret_key, 'secret_access_key')

0 commit comments

Comments
 (0)