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

potiuk 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 dda8d278671 Fix `airflowctl connections import` failure when JSON 
omits `extra` field (#62662)
dda8d278671 is described below

commit dda8d2786710c72791b821f70c8b6f43c19e0b1e
Author: Leondon9 <[email protected]>
AuthorDate: Sun Mar 1 21:02:33 2026 +0000

    Fix `airflowctl connections import` failure when JSON omits `extra` field 
(#62662)
    
    * Fix `airflowctl connections import` failure when JSON omits `extra` field
    
    When the `extra` key is absent from a connection JSON entry, the default
    value `{}` (dict) is incompatible with the `ConnectionBody.extra` field
    which expects `str | None`. Removing the default lets `v.get("extra")`
    return `None`, matching the model's type annotation.
    
    closes: #62653
    
    Co-Authored-By: claude-flow <[email protected]>
    
    * Add regression test for connection import without extra field
    
    Covers the case where `extra` is omitted from the JSON input,
    which caused a Pydantic ValidationError before the fix.
    
    Co-Authored-By: claude-flow <[email protected]>
    
    ---------
    
    Co-authored-by: claude-flow <[email protected]>
---
 .../airflowctl/ctl/commands/connection_command.py  |  2 +-
 .../ctl/commands/test_connections_command.py       | 51 ++++++++++++++++++++++
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/airflow-ctl/src/airflowctl/ctl/commands/connection_command.py 
b/airflow-ctl/src/airflowctl/ctl/commands/connection_command.py
index 8a894202206..b689083faa2 100644
--- a/airflow-ctl/src/airflowctl/ctl/commands/connection_command.py
+++ b/airflow-ctl/src/airflowctl/ctl/commands/connection_command.py
@@ -54,7 +54,7 @@ def import_(args, api_client=NEW_API_CLIENT) -> None:
                 login=v.get("login"),
                 password=v.get("password"),
                 port=v.get("port"),
-                extra=v.get("extra", {}),
+                extra=v.get("extra"),
                 description=v.get("description", ""),
             )
             for k, v in connections_json.items()
diff --git 
a/airflow-ctl/tests/airflow_ctl/ctl/commands/test_connections_command.py 
b/airflow-ctl/tests/airflow_ctl/ctl/commands/test_connections_command.py
index a63a4b4fa6a..02b56eda99b 100644
--- a/airflow-ctl/tests/airflow_ctl/ctl/commands/test_connections_command.py
+++ b/airflow-ctl/tests/airflow_ctl/ctl/commands/test_connections_command.py
@@ -17,6 +17,7 @@
 from __future__ import annotations
 
 import json
+from unittest.mock import patch
 
 import pytest
 
@@ -24,6 +25,7 @@ from airflowctl.api.client import ClientKind
 from airflowctl.api.datamodels.generated import (
     BulkActionResponse,
     BulkResponse,
+    ConnectionBody,
     ConnectionCollectionResponse,
     ConnectionResponse,
 )
@@ -125,3 +127,52 @@ class TestCliConnectionCommands:
                 self.parser.parse_args(["connections", "import", 
expected_json_path.as_posix()]),
                 api_client=api_client,
             )
+
+    def test_import_without_extra_field(self, api_client_maker, tmp_path, 
monkeypatch):
+        """Import succeeds when JSON omits the ``extra`` field (#62653).
+
+        Before the fix, ``v.get("extra", {})`` returned ``{}`` (a dict) when
+        the key was absent, but ``ConnectionBody.extra`` expects ``str | 
None``,
+        causing a Pydantic ``ValidationError``.
+        """
+        api_client = api_client_maker(
+            path="/api/v2/connections",
+            response_json=self.bulk_response_success.model_dump(),
+            expected_http_status_code=200,
+            kind=ClientKind.CLI,
+        )
+
+        monkeypatch.chdir(tmp_path)
+        json_path = tmp_path / self.export_file_name
+        # Intentionally omit "extra" (and several other optional keys) to
+        # mirror a minimal real-world connection JSON export.
+        connection_file = {
+            self.connection_id: {
+                "conn_type": "test_type",
+                "host": "test_host",
+            }
+        }
+
+        json_path.write_text(json.dumps(connection_file))
+
+        with patch(
+            "airflowctl.ctl.commands.connection_command.ConnectionBody",
+            wraps=ConnectionBody,
+        ) as mock_body:
+            connection_command.import_(
+                self.parser.parse_args(["connections", "import", 
json_path.as_posix()]),
+                api_client=api_client,
+            )
+
+        # Verify that ``extra`` was passed as None (not {} which would fail
+        # Pydantic validation) and all other absent keys default correctly.
+        mock_body.assert_called_once_with(
+            connection_id=self.connection_id,
+            conn_type="test_type",
+            host="test_host",
+            login=None,
+            password=None,
+            port=None,
+            extra=None,
+            description="",
+        )

Reply via email to