Skip to content

Commit d796878

Browse files
authored
Implement pre-existing session support for dynamodb catalog (#104)
1 parent 8f7927b commit d796878

File tree

4 files changed

+51
-4
lines changed

4 files changed

+51
-4
lines changed

mkdocs/docs/configuration.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,19 @@ catalog:
218218
table-name: iceberg
219219
```
220220

221+
If you prefer to pass the credentials explicitly to the client instead of relying on environment variables,
222+
223+
```yaml
224+
catalog:
225+
default:
226+
type: dynamodb
227+
table-name: iceberg
228+
aws_access_key_id: <ACCESS_KEY_ID>
229+
aws_secret_access_key: <SECRET_ACCESS_KEY>
230+
aws_session_token: <SESSION_TOKEN>
231+
region_name: <REGION_NAME>
232+
```
233+
221234
# Concurrency
222235

223236
PyIceberg uses multiple threads to parallelize operations. The number of workers can be configured by supplying a `max-workers` entry in the configuration file, or by setting the `PYICEBERG_MAX_WORKERS` environment variable. The default value depends on the system hardware and Python version. See [the Python documentation](https://docs.python.org/3/library/concurrent.futures.html#threadpoolexecutor) for more details.

mkdocs/docs/contributing.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ For the development, Poetry is used for packing and dependency management. You c
3030
pip install poetry
3131
```
3232

33-
If you have an older version of pip and virtualenv you need to update these:
33+
Make sure you're using an up-to-date environment from venv
3434

3535
```bash
3636
pip install --upgrade virtualenv pip
37+
python -m venv ./venv
38+
source ./venv/bin/activate
3739
```
3840

3941
To get started, you can run `make install`, which installs Poetry and all the dependencies of the Iceberg library. This also installs the development dependencies. If you don't want to install the development dependencies, you need to install using `poetry install --no-dev`.

pyiceberg/catalog/dynamodb.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,15 @@
8080
class DynamoDbCatalog(Catalog):
8181
def __init__(self, name: str, **properties: str):
8282
super().__init__(name, **properties)
83-
self.dynamodb = boto3.client(DYNAMODB_CLIENT)
83+
session = boto3.Session(
84+
profile_name=properties.get("profile_name"),
85+
region_name=properties.get("region_name"),
86+
botocore_session=properties.get("botocore_session"),
87+
aws_access_key_id=properties.get("aws_access_key_id"),
88+
aws_secret_access_key=properties.get("aws_secret_access_key"),
89+
aws_session_token=properties.get("aws_session_token"),
90+
)
91+
self.dynamodb = session.client(DYNAMODB_CLIENT)
8492
self.dynamodb_table_name = self.properties.get(DYNAMODB_TABLE_NAME, DYNAMODB_TABLE_NAME_DEFAULT)
8593
self._ensure_catalog_table_exists_or_create()
8694

tests/catalog/test_dynamodb.py

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,20 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17-
from typing import List
17+
from typing import Any, Dict, List
1818

1919
import boto3
2020
import pytest
2121
from moto import mock_dynamodb
22+
from unittest import mock
2223

2324
from pyiceberg.catalog import METADATA_LOCATION, TABLE_TYPE
2425
from pyiceberg.catalog.dynamodb import (
2526
DYNAMODB_COL_CREATED_AT,
2627
DYNAMODB_COL_IDENTIFIER,
2728
DYNAMODB_COL_NAMESPACE,
2829
DYNAMODB_TABLE_NAME_DEFAULT,
30+
ACTIVE,
2931
DynamoDbCatalog,
3032
_add_property_prefix,
3133
)
@@ -47,12 +49,13 @@ def test_create_dynamodb_catalog_with_table_name(_dynamodb, _bucket_initialize:
4749
DynamoDbCatalog("test_ddb_catalog")
4850
response = _dynamodb.describe_table(TableName=DYNAMODB_TABLE_NAME_DEFAULT)
4951
assert response["Table"]["TableName"] == DYNAMODB_TABLE_NAME_DEFAULT
52+
assert response["Table"]["TableStatus"] == ACTIVE
5053

5154
custom_table_name = "custom_table_name"
5255
DynamoDbCatalog("test_ddb_catalog", **{"table-name": custom_table_name})
5356
response = _dynamodb.describe_table(TableName=custom_table_name)
5457
assert response["Table"]["TableName"] == custom_table_name
55-
58+
assert response["Table"]["TableStatus"] == ACTIVE
5659

5760
@mock_dynamodb
5861
def test_create_table_with_database_location(
@@ -506,3 +509,24 @@ def test_update_namespace_properties_overlap_update_removal(_bucket_initialize:
506509
test_catalog.update_namespace_properties(database_name, removals, updates)
507510
# should not modify the properties
508511
assert test_catalog.load_namespace_properties(database_name) == test_properties
512+
513+
def test_passing_provided_profile() -> None:
514+
catalog_name = "test_ddb_catalog"
515+
session_props = {
516+
"aws_access_key_id": "abc",
517+
"aws_secret_access_key": "def",
518+
"aws_session_token": "ghi",
519+
"region_name": "eu-central-1",
520+
"botocore_session": None,
521+
"profile_name": None
522+
}
523+
props = {"py-io-impl": "pyiceberg.io.fsspec.FsspecFileIO"}
524+
props.update(session_props)
525+
with mock.patch('boto3.Session', return_value=mock.Mock()) as mock_session:
526+
mock_client = mock.Mock()
527+
mock_session.return_value.client.return_value = mock_client
528+
mock_client.describe_table.return_value = {'Table': {'TableStatus': 'ACTIVE'}}
529+
test_catalog = DynamoDbCatalog(catalog_name, **props)
530+
assert test_catalog.dynamodb is mock_client
531+
mock_session.assert_called_with(**session_props)
532+
assert test_catalog.dynamodb is mock_session().client()

0 commit comments

Comments
 (0)