Skip to content

Commit 59dfe20

Browse files
author
Alexandra Popova
committed
fix storage credentials type
1 parent e309dea commit 59dfe20

2 files changed

Lines changed: 30 additions & 6 deletions

File tree

pyiceberg/catalog/rest/__init__.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,16 @@ def _retry_hook(retry_state: RetryCallState) -> None:
152152
}
153153

154154

155+
class StorageCredential(IcebergBaseModel):
156+
prefix: str = Field()
157+
config: Properties = Field()
158+
159+
155160
class TableResponse(IcebergBaseModel):
156161
metadata_location: Optional[str] = Field(alias="metadata-location", default=None)
157162
metadata: TableMetadata
158163
config: Properties = Field(default_factory=dict)
159-
storage_credentials: Optional[Properties] = Field(alias="storage-credentials", default=None)
164+
storage_credentials: Optional[List[StorageCredential]] = Field(alias="storage-credentials", default=None)
160165

161166

162167
class CreateTableRequest(IcebergBaseModel):
@@ -457,7 +462,7 @@ def _response_to_table(self, identifier_tuple: Tuple[str, ...], table_response:
457462
io=self._load_file_io(
458463
{
459464
**table_response.metadata.properties,
460-
**(table_response.storage_credentials or table_response.config),
465+
**self._get_credentials(table_response.storage_credentials, table_response.config),
461466
},
462467
table_response.metadata_location,
463468
),
@@ -473,13 +478,27 @@ def _response_to_staged_table(self, identifier_tuple: Tuple[str, ...], table_res
473478
io=self._load_file_io(
474479
{
475480
**table_response.metadata.properties,
476-
**(table_response.storage_credentials or table_response.config),
481+
**self._get_credentials(table_response.storage_credentials, table_response.config),
477482
},
478483
table_response.metadata_location,
479484
),
480485
catalog=self,
481486
)
482487

488+
def _get_credentials(self, storage_credentials: List[StorageCredential], config: Properties) -> Properties:
489+
if storage_credentials:
490+
return self._get_storage_credentials(storage_credentials)
491+
else:
492+
return config
493+
494+
@staticmethod
495+
def _get_storage_credentials(storage_credentials: List[StorageCredential]) -> Properties:
496+
credentials: List[StorageCredential] = [sc for sc in storage_credentials if sc.prefix.startswith("s3")]
497+
if len(credentials) > 1:
498+
raise ValueError("Multiple S3 storage credentials found")
499+
elif len(credentials) == 1:
500+
return credentials[0].config
501+
483502
def _refresh_token(self) -> None:
484503
# Reactive token refresh is atypical - we should proactively refresh tokens in a separate thread
485504
# instead of retrying on Auth Exceptions. Keeping refresh behavior for the LegacyOAuth2AuthManager

tests/catalog/test_rest.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -865,9 +865,14 @@ def test_storage_credentials_over_config(rest_mock: Mocker, example_table_metada
865865
"config": {
866866
AWS_ACCESS_KEY_ID: "from_config",
867867
},
868-
"storage-credentials": {
869-
AWS_ACCESS_KEY_ID: "from_storage_credentials",
870-
},
868+
"storage-credentials": [
869+
{
870+
"prefix": "s3://warehouse/database/",
871+
"config": {
872+
AWS_ACCESS_KEY_ID: "from_storage_credentials",
873+
},
874+
}
875+
],
871876
}
872877

873878
rest_mock.get(

0 commit comments

Comments
 (0)