This is an automated email from the ASF dual-hosted git repository.

shahar1 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new e2372bbf0aa Read the legacy extra__google_cloud_platform__ prefix for 
GCS credentials (#73613)
e2372bbf0aa is described below

commit e2372bbf0aa5d0e4a370734bb1d8ba808f6e8c00
Author: Pankaj Singh <[email protected]>
AuthorDate: Thu Sep 24 01:29:45 2026 +0530

    Read the legacy extra__google_cloud_platform__ prefix for GCS credentials 
(#73613)
    
    GoogleBaseHook still falls back to fields written as
    extra__google_cloud_platform__<name> -- the spelling older Airflow
    connection UIs used for custom extra fields. This code only looked at the
    bare key, so a connection created that way had its key_path silently
    invisible and the unsupported-field guard never saw a prefixed
    impersonation_chain.
---
 .../providers/common/sql/datafusion/engine.py      | 14 +++++++++++---
 .../unit/common/sql/datafusion/test_engine.py      | 22 ++++++++++++++++++++++
 2 files changed, 33 insertions(+), 3 deletions(-)

diff --git 
a/providers/common/sql/src/airflow/providers/common/sql/datafusion/engine.py 
b/providers/common/sql/src/airflow/providers/common/sql/datafusion/engine.py
index f35bd5786ab..1b8a3998ef6 100644
--- a/providers/common/sql/src/airflow/providers/common/sql/datafusion/engine.py
+++ b/providers/common/sql/src/airflow/providers/common/sql/datafusion/engine.py
@@ -153,6 +153,14 @@ class DataFusionEngine(LoggingMixin):
                     conf[key] = conn.extra_dejson[key]
             return conf
 
+        def _get_gcp_extra_field(extra_dejson: dict[str, Any], field_name: 
str) -> Any:
+            # Older Airflow connection UIs wrote custom extra fields as
+            # extra__google_cloud_platform__<field_name> instead of the bare 
key; GoogleBaseHook
+            # still reads that legacy spelling as a fallback, so this must too.
+            if field_name in extra_dejson:
+                return extra_dejson[field_name]
+            return 
extra_dejson.get(f"extra__google_cloud_platform__{field_name}")
+
         match conn.conn_type:
             case "aws":
                 try:
@@ -179,14 +187,14 @@ class DataFusionEngine(LoggingMixin):
             case "google_cloud_platform":
                 extra_dejson = conn.extra_dejson
                 for unsupported_field in ("key_secret_name", 
"credential_config_file", "impersonation_chain"):
-                    if extra_dejson.get(unsupported_field):
+                    if _get_gcp_extra_field(extra_dejson, unsupported_field):
                         raise ValueError(
                             f"Connection field {unsupported_field!r} is not 
supported for DataFusion "
                             "GCS access; only key_path, keyfile_dict, 
GOOGLE_APPLICATION_CREDENTIALS, or "
                             "ambient credentials (gcloud ADC file / metadata 
server) are used."
                         )
-                key_path = extra_dejson.get("key_path") or None
-                keyfile_dict = extra_dejson.get("keyfile_dict") or None
+                key_path = _get_gcp_extra_field(extra_dejson, "key_path") or 
None
+                keyfile_dict = _get_gcp_extra_field(extra_dejson, 
"keyfile_dict") or None
                 if key_path and keyfile_dict:
                     raise ValueError(
                         "The `keyfile_dict` and `key_path` fields are mutually 
exclusive. "
diff --git 
a/providers/common/sql/tests/unit/common/sql/datafusion/test_engine.py 
b/providers/common/sql/tests/unit/common/sql/datafusion/test_engine.py
index 5e78e0c7761..10f01b43cb9 100644
--- a/providers/common/sql/tests/unit/common/sql/datafusion/test_engine.py
+++ b/providers/common/sql/tests/unit/common/sql/datafusion/test_engine.py
@@ -372,6 +372,28 @@ class TestDataFusionEngine:
         with pytest.raises(ValueError, match=f"{unsupported_field!r} is not 
supported"):
             engine._get_credentials(mock_conn)
 
+    def test_get_credentials_gcs_reads_legacy_extra_prefixed_key_path(self):
+        """Older Airflow connection UIs wrote custom extra fields as
+        extra__google_cloud_platform__<field>; GoogleBaseHook still reads that 
spelling."""
+        mock_conn = MagicMock()
+        mock_conn.conn_type = "google_cloud_platform"
+        mock_conn.extra_dejson = {"extra__google_cloud_platform__key_path": 
"/path/to/key.json"}
+        engine = DataFusionEngine()
+
+        credentials, extra_config = engine._get_credentials(mock_conn)
+
+        assert credentials == {"key_path": "/path/to/key.json"}
+        assert extra_config == {}
+
+    def 
test_get_credentials_gcs_rejects_legacy_extra_prefixed_unsupported_field(self):
+        mock_conn = MagicMock()
+        mock_conn.conn_type = "google_cloud_platform"
+        mock_conn.extra_dejson = 
{"extra__google_cloud_platform__impersonation_chain": "some-chain"}
+        engine = DataFusionEngine()
+
+        with pytest.raises(ValueError, match="'impersonation_chain' is not 
supported"):
+            engine._get_credentials(mock_conn)
+
     def test_get_credentials_unknown_type(self):
         mock_conn = MagicMock()
         mock_conn.conn_type = "dummy"

Reply via email to