|
104 | 104 | Capability.V1_DELETE_TABLE, |
105 | 105 | Capability.V1_RENAME_TABLE, |
106 | 106 | Capability.V1_REGISTER_TABLE, |
107 | | - Capability.V1_LOAD_CREDENTIALS, |
108 | 107 | Capability.V1_LIST_VIEWS, |
109 | 108 | Capability.V1_LOAD_VIEW, |
110 | 109 | Capability.V1_VIEW_EXISTS, |
@@ -162,17 +161,22 @@ def example_view_metadata_rest_json(example_view_metadata_v1: dict[str, Any]) -> |
162 | 161 | } |
163 | 162 |
|
164 | 163 |
|
| 164 | +def _mock_config_response(requests_mock: Mocker, endpoints: list[Endpoint] | None = None) -> None: |
| 165 | + endpoints = TEST_SUPPORTED_ENDPOINTS if endpoints is None else endpoints |
| 166 | + requests_mock.get( |
| 167 | + f"{TEST_URI}v1/config", |
| 168 | + json={"defaults": {}, "overrides": {}, "endpoints": [str(endpoint) for endpoint in endpoints]}, |
| 169 | + status_code=200, |
| 170 | + ) |
| 171 | + |
| 172 | + |
165 | 173 | @pytest.fixture |
166 | 174 | def rest_mock(requests_mock: Mocker) -> Mocker: |
167 | 175 | """Takes the default requests_mock and adds the config endpoint to it |
168 | 176 |
|
169 | 177 | This endpoint is called when initializing the rest catalog |
170 | 178 | """ |
171 | | - requests_mock.get( |
172 | | - f"{TEST_URI}v1/config", |
173 | | - json={"defaults": {}, "overrides": {}, "endpoints": [str(endpoint) for endpoint in TEST_SUPPORTED_ENDPOINTS]}, |
174 | | - status_code=200, |
175 | | - ) |
| 179 | + _mock_config_response(requests_mock) |
176 | 180 | return requests_mock |
177 | 181 |
|
178 | 182 |
|
@@ -1452,10 +1456,11 @@ def test_load_table_200_loading_mode( |
1452 | 1456 |
|
1453 | 1457 |
|
1454 | 1458 | def test_load_table_honor_access_delegation( |
1455 | | - rest_mock: Mocker, example_table_metadata_with_snapshot_v1_rest_json: dict[str, Any] |
| 1459 | + requests_mock: Mocker, example_table_metadata_with_snapshot_v1_rest_json: dict[str, Any] |
1456 | 1460 | ) -> None: |
| 1461 | + _mock_config_response(requests_mock, [*TEST_SUPPORTED_ENDPOINTS, Capability.V1_LOAD_CREDENTIALS]) |
1457 | 1462 | test_headers_with_remote_signing = {**TEST_HEADERS, "X-Iceberg-Access-Delegation": "remote-signing"} |
1458 | | - rest_mock.get( |
| 1463 | + requests_mock.get( |
1459 | 1464 | f"{TEST_URI}v1/namespaces/fokko/tables/table", |
1460 | 1465 | json=example_table_metadata_with_snapshot_v1_rest_json, |
1461 | 1466 | status_code=200, |
@@ -3114,9 +3119,12 @@ def test_resolve_storage_credentials_empty() -> None: |
3114 | 3119 | assert RestCatalog._resolve_storage_credentials([], None) == {} |
3115 | 3120 |
|
3116 | 3121 |
|
3117 | | -def test_load_table_with_storage_credentials(rest_mock: Mocker, example_table_metadata_with_snapshot_v1: dict[str, Any]) -> None: |
| 3122 | +def test_load_table_with_storage_credentials( |
| 3123 | + requests_mock: Mocker, example_table_metadata_with_snapshot_v1: dict[str, Any] |
| 3124 | +) -> None: |
| 3125 | + _mock_config_response(requests_mock, [*TEST_SUPPORTED_ENDPOINTS, Capability.V1_LOAD_CREDENTIALS]) |
3118 | 3126 | metadata_location = "s3://warehouse/database/table/metadata/00001.metadata.json" |
3119 | | - rest_mock.get( |
| 3127 | + requests_mock.get( |
3120 | 3128 | f"{TEST_URI}v1/namespaces/fokko/tables/table", |
3121 | 3129 | json={ |
3122 | 3130 | "metadata-location": metadata_location, |
@@ -3146,10 +3154,62 @@ def test_load_table_with_storage_credentials(rest_mock: Mocker, example_table_me |
3146 | 3154 | assert table.io.properties["s3.access-key-id"] == "vended-key" |
3147 | 3155 | assert table.io.properties["s3.secret-access-key"] == "vended-secret" |
3148 | 3156 | assert table.io.properties["s3.session-token"] == "vended-token" |
| 3157 | + assert len(requests_mock.request_history) == 2 |
3149 | 3158 |
|
3150 | 3159 |
|
3151 | | -def test_load_credentials_with_longest_prefix(rest_mock: Mocker) -> None: |
3152 | | - rest_mock.get( |
| 3160 | +def test_load_table_loads_credentials_when_endpoint_supported( |
| 3161 | + requests_mock: Mocker, example_table_metadata_with_snapshot_v1: dict[str, Any] |
| 3162 | +) -> None: |
| 3163 | + _mock_config_response(requests_mock, [*TEST_SUPPORTED_ENDPOINTS, Capability.V1_LOAD_CREDENTIALS]) |
| 3164 | + metadata_location = "s3://warehouse/database/table/metadata/00001.metadata.json" |
| 3165 | + requests_mock.get( |
| 3166 | + f"{TEST_URI}v1/namespaces/fokko/tables/table", |
| 3167 | + json={ |
| 3168 | + "metadata-location": metadata_location, |
| 3169 | + "metadata": example_table_metadata_with_snapshot_v1, |
| 3170 | + "config": { |
| 3171 | + "s3.access-key-id": "from-config", |
| 3172 | + "s3.secret-access-key": "from-config-secret", |
| 3173 | + }, |
| 3174 | + }, |
| 3175 | + status_code=200, |
| 3176 | + request_headers=TEST_HEADERS, |
| 3177 | + ) |
| 3178 | + requests_mock.get( |
| 3179 | + f"{TEST_URI}v1/namespaces/fokko/tables/table/credentials", |
| 3180 | + json={ |
| 3181 | + "storage-credentials": [ |
| 3182 | + { |
| 3183 | + "prefix": "s3://warehouse/database/", |
| 3184 | + "config": {"s3.access-key-id": "short-prefix-key"}, |
| 3185 | + }, |
| 3186 | + { |
| 3187 | + "prefix": "s3://warehouse/database/table", |
| 3188 | + "config": { |
| 3189 | + "s3.access-key-id": "long-prefix-key", |
| 3190 | + "s3.secret-access-key": "long-prefix-secret", |
| 3191 | + }, |
| 3192 | + }, |
| 3193 | + ], |
| 3194 | + }, |
| 3195 | + status_code=200, |
| 3196 | + request_headers=TEST_HEADERS, |
| 3197 | + ) |
| 3198 | + catalog = RestCatalog("rest", uri=TEST_URI, token=TEST_TOKEN) |
| 3199 | + table = catalog.load_table(("fokko", "table")) |
| 3200 | + |
| 3201 | + assert table.io.properties["s3.access-key-id"] == "long-prefix-key" |
| 3202 | + assert table.io.properties["s3.secret-access-key"] == "long-prefix-secret" |
| 3203 | + assert [request.url for request in requests_mock.request_history] == [ |
| 3204 | + f"{TEST_URI}v1/config", |
| 3205 | + f"{TEST_URI}v1/namespaces/fokko/tables/table", |
| 3206 | + f"{TEST_URI}v1/namespaces/fokko/tables/table/credentials", |
| 3207 | + ] |
| 3208 | + |
| 3209 | + |
| 3210 | +def test_load_credentials_with_longest_prefix(requests_mock: Mocker) -> None: |
| 3211 | + _mock_config_response(requests_mock, [*TEST_SUPPORTED_ENDPOINTS, Capability.V1_LOAD_CREDENTIALS]) |
| 3212 | + requests_mock.get( |
3153 | 3213 | f"{TEST_URI}v1/namespaces/fokko/tables/table/credentials", |
3154 | 3214 | json={ |
3155 | 3215 | "storage-credentials": [ |
@@ -3177,7 +3237,7 @@ def test_load_credentials_with_longest_prefix(rest_mock: Mocker) -> None: |
3177 | 3237 | ) |
3178 | 3238 |
|
3179 | 3239 | assert credentials == {"s3.access-key-id": "long-prefix-key", "s3.secret-access-key": "long-prefix-secret"} |
3180 | | - assert rest_mock.last_request.url == f"{TEST_URI}v1/namespaces/fokko/tables/table/credentials" |
| 3240 | + assert requests_mock.last_request.url == f"{TEST_URI}v1/namespaces/fokko/tables/table/credentials" |
3181 | 3241 |
|
3182 | 3242 |
|
3183 | 3243 | def test_load_table_without_storage_credentials( |
|
0 commit comments