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

henry3260 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 0014422047c Document that connection secrets without conn_type remain 
supported (#69780)
0014422047c is described below

commit 0014422047c49184540e2e1c0b9c819749d925fa
Author: Henry Chen <[email protected]>
AuthorDate: Thu Jul 23 18:08:29 2026 +0800

    Document that connection secrets without conn_type remain supported (#69780)
    
    * Reject connection secrets without a connection type
    
    Prevent malformed JSON secrets from being reported as missing connections 
at runtime.
    
    * Keep Airflow 2-era connection secrets working and document why
    
    Review on the PR pointed out that rejecting JSON connection secrets
    without a conn_type would regress the Airflow 2 -> 3 migration
    compatibility deliberately established in #61728: secrets stored by
    Airflow 2-era backends (e.g. AWS Secrets Manager) commonly omit both
    conn_type and uri, and the worker-local secrets backend path must keep
    resolving them. Replace the rejection with a comment at the
    deserialization site and a regression test, so the compatibility
    guarantee is visible to future readers and enforced by CI.
    
    Co-Authored-By: Claude Fable 5 <[email protected]>
    
    * Simplify Airflow 2 compatibility comments and add removal TODO
    
    Apply review suggestions: tighten the migration-compatibility comment and
    test docstring, and mark the compatibility path for removal once the
    minimum supported Airflow version in providers is 3.0.
    
    ---------
    
    Co-authored-by: Claude Fable 5 <[email protected]>
---
 .../src/airflow_shared/secrets_backend/base.py            |  7 +++++++
 shared/secrets_backend/tests/secrets_backend/test_base.py | 15 +++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/shared/secrets_backend/src/airflow_shared/secrets_backend/base.py 
b/shared/secrets_backend/src/airflow_shared/secrets_backend/base.py
index e61197d2baa..77c08be45f1 100644
--- a/shared/secrets_backend/src/airflow_shared/secrets_backend/base.py
+++ b/shared/secrets_backend/src/airflow_shared/secrets_backend/base.py
@@ -122,6 +122,13 @@ class BaseSecretsBackend(ABC):
     def _deserialize_connection_value(conn_class: type, conn_id: str, value: 
str):
         value = value.strip()
         if value[0] == "{":
+            # JSON secrets stored by Airflow 2 backends may lack both 
"conn_type"
+            # and "uri" (e.g. {"host": ..., "login": ..., "password": ...}). 
This is
+            # valid: conn_type is intentionally optional on the SDK Connection 
model
+            # for Airflow 2 -> 3 migration compatibility.
+            # Check: https://github.com/apache/airflow/pull/61728
+            # TODO: Remove this compatibility once the minimum supported 
Airflow
+            #   version in providers is 3.0.
             return conn_class.from_json(value=value, conn_id=conn_id)  # type: 
ignore[attr-defined]
 
         # TODO: Only sdk has from_uri defined on it. Is it worthwhile 
developing the core path or not?
diff --git a/shared/secrets_backend/tests/secrets_backend/test_base.py 
b/shared/secrets_backend/tests/secrets_backend/test_base.py
index e14e6204243..32d9993ae1e 100644
--- a/shared/secrets_backend/tests/secrets_backend/test_base.py
+++ b/shared/secrets_backend/tests/secrets_backend/test_base.py
@@ -124,6 +124,21 @@ class TestBaseSecretsBackend:
         assert conn.conn_id == "test_conn"
         assert conn._kwargs["conn_type"] == "mysql"
 
+    def test_deserialize_connection_json_without_conn_type(self):
+        """
+        Guards the Airflow 2 -> 3 migration compatibility established in
+        https://github.com/apache/airflow/pull/61728.
+        """
+        backend = _TestBackend()
+        backend._set_connection_class(MockConnection)
+
+        conn = backend.deserialize_connection(
+            "test_conn", '{"host": "example.com", "login": "admin", 
"password": "secret"}'
+        )
+        assert isinstance(conn, MockConnection)
+        assert conn.conn_id == "test_conn"
+        assert conn._kwargs == {"host": "example.com", "login": "admin", 
"password": "secret"}
+
     def test_deserialize_connection_uri(self, sample_conn_uri):
         """Test deserialize_connection with URI format through _TestBackend."""
         backend = _TestBackend()

Reply via email to