rinzool opened a new issue, #2655:
URL: https://github.com/apache/iceberg-python/issues/2655

   ### Apache Iceberg version
   
   0.10.0 (latest release)
   
   ### Please describe the bug 🐞
   
   # Description
   Since version 0.10.0 it is not possible to create a Polaris catalog with 
`credential` parameter. 
   
   For example:
   ```python
   catalog_parameters = {
       "type": "rest",
       # ...
       "scope": "PRINCIPAL_ROLE:ALL",
       "header.Polaris-Realm": "my-realm",
       "credential": f"{client_id}:{client_secret}"
   }
   
   catalog = load_catalog("default, **catalog_parameters)
   ```
   
   This code fails with error `RESTError: MissingOrInvalidRealm: Missing or 
invalid realm`.
   
   The exact same code works with pyiceberg 0.9.1.
   
   
   # Cause
   
   Polaris needs header `Polaris-Realm`. 
   
   We can see in the full stacktrace (see below) that the error occurs when we 
create the AuthManager line 266: 
https://github.com/apache/iceberg-python/blob/pyiceberg-0.10.0/pyiceberg/catalog/rest/__init__.py#L266.
   
   But headers are injected **after** initializing AuthManager at line 269:
   
https://github.com/apache/iceberg-python/blob/pyiceberg-0.10.0/pyiceberg/catalog/rest/__init__.py#L269.
   
   
   <details>
   <summary>Full stacktrace</summary>
   
   ```
   File 
[/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/__init__.py:128](https://poc-dwh-qfn.forepaas.io/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/__init__.py#line=127),
 in load_rest(name, conf)
       125 def load_rest(name: str, conf: Properties) -> Catalog:
       126     from pyiceberg.catalog.rest import RestCatalog
   --> 128     return RestCatalog(name, **conf)
   
   File 
[/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/__init__.py:234](https://poc-dwh-qfn.forepaas.io/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/__init__.py#line=233),
 in RestCatalog.__init__(self, name, **properties)
       232 super().__init__(name, **properties)
       233 self.uri = properties[URI]
   --> 234 self._fetch_config()
       235 self._session = self._create_session()
   
   File 
[/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/__init__.py:364](https://poc-dwh-qfn.forepaas.io/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/__init__.py#line=363),
 in RestCatalog._fetch_config(self)
       361 if warehouse_location := self.properties.get(WAREHOUSE_LOCATION):
       362     params[WAREHOUSE_LOCATION] = warehouse_location
   --> 364 with self._create_session() as session:
       365     response = session.get(self.url(Endpoints.get_config, 
prefixed=False), params=params)
       366 try:
   
   File 
[/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/__init__.py:266](https://poc-dwh-qfn.forepaas.io/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/__init__.py#line=265),
 in RestCatalog._create_session(self)
       264     session.auth = 
AuthManagerAdapter(AuthManagerFactory.create(auth_impl or auth_type, 
auth_type_config))
       265 else:
   --> 266     session.auth = 
AuthManagerAdapter(self._create_legacy_oauth2_auth_manager(session))
       268 # Set HTTP headers
       269 self._config_headers(session)
   
   File 
[/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/__init__.py:295](https://poc-dwh-qfn.forepaas.io/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/__init__.py#line=294),
 in RestCatalog._create_legacy_oauth2_auth_manager(self, session)
       285 auth_url = self.auth_url if client_credentials is not None else None
       287 auth_config = {
       288     "session": session,
       289     "auth_url": auth_url,
      (...)
       292     "optional_oauth_params": self._extract_optional_oauth_params(),
       293 }
   --> 295 return AuthManagerFactory.create("legacyoauth2", auth_config)
   
   File 
[/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/auth.py:321](https://poc-dwh-qfn.forepaas.io/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/auth.py#line=320),
 in AuthManagerFactory.create(cls, class_or_name, config)
       318     except Exception as err:
       319         raise ValueError(f"Could not load AuthManager class for 
'{class_or_name}'") from err
   --> 321 return manager_cls(**config)
   
   File 
[/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/auth.py:94](https://poc-dwh-qfn.forepaas.io/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/auth.py#line=93),
 in LegacyOAuth2AuthManager.__init__(self, session, auth_url, credential, 
initial_token, optional_oauth_params)
        92 self._credential = credential
        93 self._optional_oauth_params = optional_oauth_params
   ---> 94 self._refresh_token()
   
   File 
[/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/auth.py:122](https://poc-dwh-qfn.forepaas.io/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/auth.py#line=121),
 in LegacyOAuth2AuthManager._refresh_token(self)
       120 def _refresh_token(self) -> None:
       121     if self._credential is not None:
   --> 122         self._token = self._fetch_access_token(self._credential)
   
   File 
[/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/auth.py:116](https://poc-dwh-qfn.forepaas.io/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/auth.py#line=115),
 in LegacyOAuth2AuthManager._fetch_access_token(self, credential)
       114     response.raise_for_status()
       115 except HTTPError as exc:
   --> 116     _handle_non_200_response(exc, {400: OAuthError, 401: OAuthError})
       118 return TokenResponse.model_validate_json(response.text).access_token
   
   File 
[/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/response.py:111](https://poc-dwh-qfn.forepaas.io/opt/conda/lib/python3.11/site-packages/pyiceberg/catalog/rest/response.py#line=110),
 in _handle_non_200_response(exc, error_handler)
       108     errs = ", ".join(err["msg"] for err in e.errors())
       109     response = f"RESTError {exc.response.status_code}: Received 
unexpected JSON Payload: {exc.response.text}, errors: {errs}"
   --> 111 raise exception(response) from exc
   
   RESTError: MissingOrInvalidRealm: Missing or invalid realm
   ```
   
   </details>
   
   # Solution
   Move `self._config_headers(session)` instruction in the beginning of 
`_create_session` method.
   
   ### Willingness to contribute
   
   - [x] I can contribute a fix for this bug independently
   - [x] I would be willing to contribute a fix for this bug with guidance from 
the Iceberg community
   - [ ] I cannot contribute a fix for this bug at this time


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to