|
18 | 18 | from __future__ import annotations |
19 | 19 |
|
20 | 20 | import base64 |
| 21 | +import json |
21 | 22 | import os |
22 | 23 | from collections.abc import Callable |
23 | 24 | from typing import Any, cast |
@@ -2470,6 +2471,115 @@ def test_rest_catalog_oauth2_non_200_token_response(requests_mock: Mocker) -> No |
2470 | 2471 | RestCatalog("rest", **catalog_properties) # type: ignore |
2471 | 2472 |
|
2472 | 2473 |
|
| 2474 | +def _rest_catalog_properties_from_environment() -> RecursiveDict: |
| 2475 | + env_config = Config._from_environment_variables({}) |
| 2476 | + catalogs = cast(RecursiveDict, env_config["catalog"]) |
| 2477 | + return cast(RecursiveDict, catalogs["rest"]) |
| 2478 | + |
| 2479 | + |
| 2480 | +@mock.patch.dict( |
| 2481 | + os.environ, |
| 2482 | + { |
| 2483 | + "PYICEBERG_CATALOG__REST__URI": TEST_URI, |
| 2484 | + "PYICEBERG_CATALOG__REST__AUTH": json.dumps({"type": "basic", "basic": {"username": "one", "password": "two"}}), |
| 2485 | + }, |
| 2486 | + clear=True, |
| 2487 | +) |
| 2488 | +def test_rest_catalog_with_basic_auth_json_environment_variable(rest_mock: Mocker) -> None: |
| 2489 | + rest_mock.get(f"{TEST_URI}v1/config", json={"defaults": {}, "overrides": {}}, status_code=200) |
| 2490 | + |
| 2491 | + RestCatalog("rest", **_rest_catalog_properties_from_environment()) # type: ignore |
| 2492 | + |
| 2493 | + encoded_user_pass = base64.b64encode(b"one:two").decode() |
| 2494 | + assert rest_mock.last_request.headers["Authorization"] == f"Basic {encoded_user_pass}" |
| 2495 | + |
| 2496 | + |
| 2497 | +@mock.patch.dict( |
| 2498 | + os.environ, |
| 2499 | + { |
| 2500 | + "PYICEBERG_CATALOG__REST__URI": TEST_URI, |
| 2501 | + "PYICEBERG_CATALOG__REST__AUTH": json.dumps( |
| 2502 | + { |
| 2503 | + "type": "oauth2", |
| 2504 | + "oauth2": { |
| 2505 | + "client_id": "some_client_id", |
| 2506 | + "client_secret": "some_client_secret", |
| 2507 | + "token_url": f"{TEST_URI}oauth2/token", |
| 2508 | + }, |
| 2509 | + } |
| 2510 | + ), |
| 2511 | + }, |
| 2512 | + clear=True, |
| 2513 | +) |
| 2514 | +def test_rest_catalog_with_oauth2_auth_json_environment_variable(requests_mock: Mocker) -> None: |
| 2515 | + requests_mock.post( |
| 2516 | + f"{TEST_URI}oauth2/token", |
| 2517 | + json={"access_token": TEST_TOKEN, "token_type": "Bearer", "expires_in": 3600}, |
| 2518 | + status_code=200, |
| 2519 | + ) |
| 2520 | + requests_mock.get(f"{TEST_URI}v1/config", json={"defaults": {}, "overrides": {}}, status_code=200) |
| 2521 | + |
| 2522 | + catalog = RestCatalog("rest", **_rest_catalog_properties_from_environment()) # type: ignore |
| 2523 | + |
| 2524 | + assert catalog.uri == TEST_URI |
| 2525 | + |
| 2526 | + |
| 2527 | +@mock.patch.dict( |
| 2528 | + os.environ, |
| 2529 | + { |
| 2530 | + "PYICEBERG_CATALOG__REST__URI": TEST_URI, |
| 2531 | + "PYICEBERG_CATALOG__REST__AUTH": "not-valid-json", |
| 2532 | + }, |
| 2533 | + clear=True, |
| 2534 | +) |
| 2535 | +def test_rest_catalog_with_invalid_json_auth_environment_variable() -> None: |
| 2536 | + with pytest.raises(ValueError, match="Failed to parse auth configuration as JSON"): |
| 2537 | + RestCatalog("rest", **_rest_catalog_properties_from_environment()) # type: ignore |
| 2538 | + |
| 2539 | + |
| 2540 | +@mock.patch.dict( |
| 2541 | + os.environ, |
| 2542 | + { |
| 2543 | + "PYICEBERG_CATALOG__REST__URI": TEST_URI, |
| 2544 | + "PYICEBERG_CATALOG__REST__AUTH__TYPE": "basic", |
| 2545 | + "PYICEBERG_CATALOG__REST__AUTH__BASIC__USERNAME": "one", |
| 2546 | + "PYICEBERG_CATALOG__REST__AUTH__BASIC__PASSWORD": "two", |
| 2547 | + }, |
| 2548 | + clear=True, |
| 2549 | +) |
| 2550 | +def test_rest_catalog_with_basic_auth_flat_environment_variables(rest_mock: Mocker) -> None: |
| 2551 | + rest_mock.get(f"{TEST_URI}v1/config", json={"defaults": {}, "overrides": {}}, status_code=200) |
| 2552 | + |
| 2553 | + RestCatalog("rest", **_rest_catalog_properties_from_environment()) # type: ignore |
| 2554 | + |
| 2555 | + encoded_user_pass = base64.b64encode(b"one:two").decode() |
| 2556 | + assert rest_mock.last_request.headers["Authorization"] == f"Basic {encoded_user_pass}" |
| 2557 | + |
| 2558 | + |
| 2559 | +@mock.patch.dict( |
| 2560 | + os.environ, |
| 2561 | + { |
| 2562 | + "PYICEBERG_CATALOG__REST__URI": TEST_URI, |
| 2563 | + "PYICEBERG_CATALOG__REST__AUTH__TYPE": "oauth2", |
| 2564 | + "PYICEBERG_CATALOG__REST__AUTH__OAUTH2__CLIENT_ID": "some_client_id", |
| 2565 | + "PYICEBERG_CATALOG__REST__AUTH__OAUTH2__CLIENT_SECRET": "some_client_secret", |
| 2566 | + "PYICEBERG_CATALOG__REST__AUTH__OAUTH2__TOKEN_URL": f"{TEST_URI}oauth2/token", |
| 2567 | + }, |
| 2568 | + clear=True, |
| 2569 | +) |
| 2570 | +def test_rest_catalog_with_oauth2_auth_flat_environment_variables(requests_mock: Mocker) -> None: |
| 2571 | + requests_mock.post( |
| 2572 | + f"{TEST_URI}oauth2/token", |
| 2573 | + json={"access_token": TEST_TOKEN, "token_type": "Bearer", "expires_in": 3600}, |
| 2574 | + status_code=200, |
| 2575 | + ) |
| 2576 | + requests_mock.get(f"{TEST_URI}v1/config", json={"defaults": {}, "overrides": {}}, status_code=200) |
| 2577 | + |
| 2578 | + catalog = RestCatalog("rest", **_rest_catalog_properties_from_environment()) # type: ignore |
| 2579 | + |
| 2580 | + assert catalog.uri == TEST_URI |
| 2581 | + |
| 2582 | + |
2473 | 2583 | EXAMPLE_ENV = {"PYICEBERG_CATALOG__PRODUCTION__URI": TEST_URI} |
2474 | 2584 |
|
2475 | 2585 |
|
|
0 commit comments