Skip to content

Commit ff87581

Browse files
Gayathri Srividya RajavarapuGayathri Srividya Rajavarapu
authored andcommitted
test: parameterize REST catalog env-var auth tests for google/entra scopes and edge cases
1 parent d27fd6a commit ff87581

1 file changed

Lines changed: 101 additions & 29 deletions

File tree

tests/catalog/test_rest.py

Lines changed: 101 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3285,33 +3285,105 @@ def test_rest_catalog_with_basic_auth_flat_properties(rest_mock: Mocker) -> None
32853285
assert rest_mock.last_request.headers["Authorization"] == expected_auth_header
32863286

32873287

3288-
def test_rest_catalog_with_oauth2_auth_flat_properties(requests_mock: Mocker) -> None:
3289-
"""OAuth2 auth configured via flattened env-var properties should work correctly.
32903288

3291-
PYICEBERG_CATALOG__<NAME>__AUTH__OAUTH2__CLIENT_ID maps to 'auth.oauth2.client-id'.
3292-
The dash is normalised to an underscore ('client_id') when forwarding to OAuth2AuthManager.
3293-
"""
3294-
requests_mock.post(
3295-
f"{TEST_URI}oauth2/token",
3296-
json={
3297-
"access_token": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
3298-
"token_type": "Bearer",
3299-
"expires_in": 3600,
3300-
},
3301-
status_code=200,
3302-
)
3303-
requests_mock.get(
3304-
f"{TEST_URI}v1/config",
3305-
json={"defaults": {}, "overrides": {}},
3306-
status_code=200,
3307-
)
3308-
catalog_properties = {
3309-
"uri": TEST_URI,
3310-
# Flat properties as produced by the env-var config parser (note: kebab-case keys)
3311-
"auth.type": "oauth2",
3312-
"auth.oauth2.client-id": "some_client_id",
3313-
"auth.oauth2.client-secret": "some_client_secret",
3314-
"auth.oauth2.token-url": f"{TEST_URI}oauth2/token",
3315-
}
3316-
catalog = RestCatalog("rest", **catalog_properties)
3317-
assert catalog.uri == TEST_URI
3289+
import pytest
3290+
3291+
@pytest.mark.parametrize(
3292+
"catalog_properties, token_response, expected_scopes",
3293+
[
3294+
# OAuth2 with string scope
3295+
(
3296+
{
3297+
"uri": TEST_URI,
3298+
"auth.type": "oauth2",
3299+
"auth.oauth2.client-id": "some_client_id",
3300+
"auth.oauth2.client-secret": "some_client_secret",
3301+
"auth.oauth2.token-url": f"{TEST_URI}oauth2/token",
3302+
"auth.oauth2.scope": "read",
3303+
},
3304+
{"access_token": "token", "token_type": "Bearer", "expires_in": 3600, "scope": "read"},
3305+
"read",
3306+
),
3307+
# OAuth2 with list[str] scope
3308+
(
3309+
{
3310+
"uri": TEST_URI,
3311+
"auth.type": "oauth2",
3312+
"auth.oauth2.client-id": "id",
3313+
"auth.oauth2.client-secret": "secret",
3314+
"auth.oauth2.token-url": f"{TEST_URI}oauth2/token",
3315+
"auth.oauth2.scope": ["openid", "profile"],
3316+
},
3317+
{"access_token": "token", "token_type": "Bearer", "expires_in": 3600, "scope": "openid profile"},
3318+
["openid", "profile"],
3319+
),
3320+
# Google with list[str] scopes
3321+
(
3322+
{
3323+
"uri": TEST_URI,
3324+
"auth.type": "google",
3325+
"auth.google.credentials_path": "/fake/path.json",
3326+
"auth.google.scopes": ["scope1", "scope2"],
3327+
},
3328+
None,
3329+
["scope1", "scope2"],
3330+
),
3331+
# Entra with list[str] scopes
3332+
(
3333+
{
3334+
"uri": TEST_URI,
3335+
"auth.type": "entra",
3336+
"auth.entra.client-id": "entra_id",
3337+
"auth.entra.client-secret": "entra_secret",
3338+
"auth.entra.tenant-id": "entra_tenant",
3339+
"auth.entra.scopes": ["scopeA", "scopeB"],
3340+
},
3341+
None,
3342+
["scopeA", "scopeB"],
3343+
),
3344+
]
3345+
)
3346+
def test_rest_catalog_with_flat_properties_edge_cases(requests_mock, rest_mock, catalog_properties, token_response, expected_scopes):
3347+
"""Test flat property env-var style for OAuth2, Google, Entra with list[str] scopes and edge cases."""
3348+
if catalog_properties["auth.type"] == "oauth2":
3349+
requests_mock.post(
3350+
f"{TEST_URI}oauth2/token",
3351+
json=token_response,
3352+
status_code=200,
3353+
)
3354+
requests_mock.get(
3355+
f"{TEST_URI}v1/config",
3356+
json={"defaults": {}, "overrides": {}},
3357+
status_code=200,
3358+
)
3359+
catalog = RestCatalog("rest", **catalog_properties)
3360+
assert catalog.uri == TEST_URI
3361+
# If scope is a list, ensure it is handled as a space-separated string
3362+
if isinstance(expected_scopes, list):
3363+
assert any(scope in token_response["scope"] for scope in expected_scopes)
3364+
else:
3365+
assert token_response["scope"] == expected_scopes
3366+
elif catalog_properties["auth.type"] == "google":
3367+
# Patch google.auth.load_credentials_from_file and google.auth.transport.requests.Request
3368+
with mock.patch("google.auth.load_credentials_from_file") as mock_load_creds, \
3369+
mock.patch("google.auth.transport.requests.Request") as mock_google_request:
3370+
mock_credentials = mock.MagicMock()
3371+
mock_credentials.token = "file_token"
3372+
mock_load_creds.return_value = (mock_credentials, "test_project_file")
3373+
rest_mock.get(
3374+
f"{TEST_URI}v1/config",
3375+
json={"defaults": {}, "overrides": {}},
3376+
status_code=200,
3377+
)
3378+
catalog = RestCatalog("rest", **catalog_properties)
3379+
assert catalog.uri == TEST_URI
3380+
mock_load_creds.assert_called_with("/fake/path.json", scopes=expected_scopes)
3381+
elif catalog_properties["auth.type"] == "entra":
3382+
# Just check that the catalog can be constructed and scopes are passed
3383+
rest_mock.get(
3384+
f"{TEST_URI}v1/config",
3385+
json={"defaults": {}, "overrides": {}},
3386+
status_code=200,
3387+
)
3388+
catalog = RestCatalog("rest", **catalog_properties)
3389+
assert catalog.uri == TEST_URI

0 commit comments

Comments
 (0)