This is an automated email from the ASF dual-hosted git repository.
turaga 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 4f43181a0f6 Auto-discover DB managers from provider.yaml (#62308)
4f43181a0f6 is described below
commit 4f43181a0f6375290893305f63923d58366e16ca
Author: Dheeraj Turaga <[email protected]>
AuthorDate: Mon Feb 23 14:16:53 2026 -0600
Auto-discover DB managers from provider.yaml (#62308)
* Auto-discover DB managers from provider.yaml
DB managers (EdgeDBManager, FABDBManager) previously required manual
configuration via AIRFLOW__DATABASE__EXTERNAL_DB_MANAGERS. They are now
declared in provider.yaml under a new db-managers key and picked up
automatically by ProvidersManager, matching the pattern used by executors,
auth-managers, and secrets-backends.
* Fix some unit tests
* Fix static checks
* Fix more unit tests
* fix: use inspector check for edge_job index creation on MySQL
MySQL does not support CREATE INDEX IF NOT EXISTS, causing the edge3
migration to fail when running on MySQL. Replace the if_not_exists=True
flag with an explicit inspector-based existence check, which works
across all supported database backends.
* fix: use inspector check for FAB index creation on MySQL
MySQL does not support CREATE INDEX IF NOT EXISTS. Replace the
if_not_exists=True flag on batch_op.create_index calls in the FAB
bootstrap migration with explicit inspector-based existence checks,
matching the pattern already applied to the edge3 migration.
* hopefully the final unit test fix
* fix: ignore edge3 tables in schema sync test for lower-dep CI
---
.../src/airflow/config_templates/config.yml | 6 ++---
airflow-core/src/airflow/provider.yaml.schema.json | 7 +++++
airflow-core/src/airflow/provider_info.schema.json | 7 +++++
airflow-core/src/airflow/providers_manager.py | 20 ++++++++++++++
airflow-core/src/airflow/utils/db_manager.py | 21 ++++++++++-----
airflow-core/tests/unit/utils/test_db.py | 21 +++++++++------
providers/edge3/provider.yaml | 3 +++
.../airflow/providers/edge3/get_provider_info.py | 1 +
.../versions/0001_3_0_0_create_edge_tables.py | 6 ++++-
.../edge3/src/airflow/providers/edge3/models/db.py | 10 +++++--
providers/edge3/tests/unit/edge3/models/test_db.py | 31 +++++++++++++++++-----
.../edge3/plugins/test_edge_executor_plugin.py | 11 ++++++--
providers/fab/provider.yaml | 3 +++
.../src/airflow/providers/fab/get_provider_info.py | 1 +
.../0000_1_4_0_create_ab_tables_if_missing.py | 18 ++++++++-----
.../unit/fab/auth_manager/test_fab_auth_manager.py | 3 +++
.../unit/fab/db_manager/test_fab_db_manager.py | 2 +-
17 files changed, 136 insertions(+), 35 deletions(-)
diff --git a/airflow-core/src/airflow/config_templates/config.yml
b/airflow-core/src/airflow/config_templates/config.yml
index 63c1a574a2d..29ad76c5d93 100644
--- a/airflow-core/src/airflow/config_templates/config.yml
+++ b/airflow-core/src/airflow/config_templates/config.yml
@@ -687,9 +687,9 @@ database:
default: "True"
external_db_managers:
description: |
- List of DB managers to use to migrate external tables in airflow
database. The managers must inherit
- from BaseDBManager. If ``FabAuthManager`` is configured in the
environment,
- ``airflow.providers.fab.auth_manager.models.db.FABDBManager`` is
automatically added.
+ Additional DB managers to include when migrating external tables in
the Airflow
+ database, beyond those automatically discovered from installed
providers.
+ The managers must inherit from BaseDBManager.
version_added: 3.0.0
type: string
example: "airflow.providers.fab.auth_manager.models.db.FABDBManager"
diff --git a/airflow-core/src/airflow/provider.yaml.schema.json
b/airflow-core/src/airflow/provider.yaml.schema.json
index 25ca731a83b..1fdf1844620 100644
--- a/airflow-core/src/airflow/provider.yaml.schema.json
+++ b/airflow-core/src/airflow/provider.yaml.schema.json
@@ -539,6 +539,13 @@
"type": "string"
}
},
+ "db-managers": {
+ "type": "array",
+ "description": "DB manager class names",
+ "items": {
+ "type": "string"
+ }
+ },
"cli": {
"type": "array",
"description": "CLI command functions exposed by the provider",
diff --git a/airflow-core/src/airflow/provider_info.schema.json
b/airflow-core/src/airflow/provider_info.schema.json
index 3e408b07536..7c3eea12591 100644
--- a/airflow-core/src/airflow/provider_info.schema.json
+++ b/airflow-core/src/airflow/provider_info.schema.json
@@ -355,6 +355,13 @@
"type": "string"
}
},
+ "db-managers": {
+ "type": "array",
+ "description": "DB manager class names",
+ "items": {
+ "type": "string"
+ }
+ },
"cli": {
"type": "array",
"description": "CLI command functions exposed by the provider",
diff --git a/airflow-core/src/airflow/providers_manager.py
b/airflow-core/src/airflow/providers_manager.py
index 84cb95d656f..544311c4701 100644
--- a/airflow-core/src/airflow/providers_manager.py
+++ b/airflow-core/src/airflow/providers_manager.py
@@ -427,6 +427,7 @@ class ProvidersManager(LoggingMixin):
self._executor_class_name_set: set[str] = set()
self._executor_without_check_set: set[tuple[str, str]] = set()
self._queue_class_name_set: set[str] = set()
+ self._db_manager_class_name_set: set[str] = set()
self._provider_configs: dict[str, dict[str, Any]] = {}
self._trigger_info_set: set[TriggerInfo] = set()
self._notification_info_set: set[NotificationInfo] = set()
@@ -583,6 +584,12 @@ class ProvidersManager(LoggingMixin):
self.initialize_providers_list()
self._discover_queues()
+ @provider_info_cache("db_managers")
+ def initialize_providers_db_managers(self):
+ """Lazy initialization of providers db_managers information."""
+ self.initialize_providers_list()
+ self._discover_db_managers()
+
@provider_info_cache("notifications")
def initialize_providers_notifications(self):
"""Lazy initialization of providers notifications information."""
@@ -1246,6 +1253,14 @@ class ProvidersManager(LoggingMixin):
if _correctness_check(provider_package, queue_class_name,
provider):
self._queue_class_name_set.add(queue_class_name)
+ def _discover_db_managers(self) -> None:
+ """Retrieve all DB managers defined in the providers."""
+ for provider_package, provider in self._provider_dict.items():
+ if provider.data.get("db-managers"):
+ for db_manager_class_name in provider.data["db-managers"]:
+ if _correctness_check(provider_package,
db_manager_class_name, provider):
+
self._db_manager_class_name_set.add(db_manager_class_name)
+
def _discover_config(self) -> None:
"""Retrieve all configs defined in the providers."""
for provider_package, provider in self._provider_dict.items():
@@ -1405,6 +1420,11 @@ class ProvidersManager(LoggingMixin):
self.initialize_providers_queues()
return sorted(self._queue_class_name_set)
+ @property
+ def db_managers(self) -> list[str]:
+ self.initialize_providers_db_managers()
+ return sorted(self._db_manager_class_name_set)
+
@property
def filesystem_module_names(self) -> list[str]:
self.initialize_providers_filesystems()
diff --git a/airflow-core/src/airflow/utils/db_manager.py
b/airflow-core/src/airflow/utils/db_manager.py
index 93959b5bf68..0c3b7b3c16b 100644
--- a/airflow-core/src/airflow/utils/db_manager.py
+++ b/airflow-core/src/airflow/utils/db_manager.py
@@ -167,20 +167,29 @@ class RunDBManager(LoggingMixin):
def __init__(self):
from airflow.api_fastapi.app import create_auth_manager
+ from airflow.providers_manager import ProvidersManager
super().__init__()
self._managers: list[BaseDBManager] = []
+
+ # Start with auto-discovered DB managers from installed providers
+ managers: list[str] = list(ProvidersManager().db_managers)
+
+ # Add any explicitly configured managers not already discovered
managers_config = conf.get("database", "external_db_managers",
fallback=None)
- if not managers_config:
- managers = []
- else:
- managers = managers_config.split(",")
- # Add DB manager specified by auth manager (if any)
+ if managers_config:
+ for m in managers_config.split(","):
+ if stripped := m.strip():
+ if stripped not in managers:
+ managers.append(stripped)
+
+ # Add DB manager declared by the configured auth manager (existing
behavior, deduplicated)
auth_manager_db_manager = create_auth_manager().get_db_manager()
if auth_manager_db_manager and auth_manager_db_manager not in managers:
managers.append(auth_manager_db_manager)
+
for module in managers:
- manager = import_string(module)
+ manager = import_string(module.strip())
self._managers.append(manager)
def validate(self):
diff --git a/airflow-core/tests/unit/utils/test_db.py
b/airflow-core/tests/unit/utils/test_db.py
index 97aa3941b3b..6a5a7b05061 100644
--- a/airflow-core/tests/unit/utils/test_db.py
+++ b/airflow-core/tests/unit/utils/test_db.py
@@ -80,14 +80,10 @@ def ensure_clean_engine_state():
@pytest.fixture
def initialized_db():
"""Ensure database is properly initialized with alembic_version table."""
- # Check if DB is already initialized
- if not _get_current_revision(settings.Session()):
- # Initialize it properly
- initdb(session=settings.Session())
-
+ session = settings.Session()
+ if not _get_current_revision(session):
+ initdb(session=session)
yield
-
- # Cleanup if needed
settings.Session.remove()
@@ -103,7 +99,8 @@ class TestDb:
# Airflow DB
for table_name, table in airflow_base.metadata.tables.items():
all_meta_data._add_table(table_name, table.schema, table)
- # External DB Managers
+ # External DB Managers — include all auto-discovered managers so the
+ # metadata matches what initialized_db migrated via initdb().
external_db_managers = RunDBManager()
for dbmanager in external_db_managers._managers:
for table_name, table in dbmanager.metadata.tables.items():
@@ -143,6 +140,14 @@ class TestDb:
lambda t: t[0] == "remove_table" and t[1].name ==
"sqlite_sequence",
# fab version table
lambda t: t[0] == "remove_table" and t[1].name ==
"alembic_version_fab",
+ # edge3 version table
+ lambda t: t[0] == "remove_table" and t[1].name ==
"alembic_version_edge3",
+ # edge3 data tables — may be present in DB from a previous initdb
run
+ # when edge3 is installed, but absent from the model in lower-dep
CI runs
+ lambda t: t[0] == "remove_table" and t[1].name == "edge_worker",
+ lambda t: t[0] == "remove_table" and t[1].name == "edge_job",
+ lambda t: t[0] == "remove_table" and t[1].name == "edge_logs",
+ lambda t: t[0] == "remove_index" and t[1].name == "rj_order",
# Ignore _xcom_archive table
lambda t: t[0] == "remove_table" and t[1].name == "_xcom_archive",
]
diff --git a/providers/edge3/provider.yaml b/providers/edge3/provider.yaml
index 573b3437394..61a374c423c 100644
--- a/providers/edge3/provider.yaml
+++ b/providers/edge3/provider.yaml
@@ -70,6 +70,9 @@ cli:
executors:
- airflow.providers.edge3.executors.EdgeExecutor
+db-managers:
+ - airflow.providers.edge3.models.db.EdgeDBManager
+
config:
edge:
description: |
diff --git a/providers/edge3/src/airflow/providers/edge3/get_provider_info.py
b/providers/edge3/src/airflow/providers/edge3/get_provider_info.py
index 393b8cf9b08..9e4c9a2bf98 100644
--- a/providers/edge3/src/airflow/providers/edge3/get_provider_info.py
+++ b/providers/edge3/src/airflow/providers/edge3/get_provider_info.py
@@ -34,6 +34,7 @@ def get_provider_info():
],
"cli":
["airflow.providers.edge3.cli.definition.get_edge_cli_commands"],
"executors": ["airflow.providers.edge3.executors.EdgeExecutor"],
+ "db-managers": ["airflow.providers.edge3.models.db.EdgeDBManager"],
"config": {
"edge": {
"description": "This section only applies if you are using the
EdgeExecutor in\n``[core]`` section above\n",
diff --git
a/providers/edge3/src/airflow/providers/edge3/migrations/versions/0001_3_0_0_create_edge_tables.py
b/providers/edge3/src/airflow/providers/edge3/migrations/versions/0001_3_0_0_create_edge_tables.py
index 53f4ab7a2eb..dc0eff53f47 100644
---
a/providers/edge3/src/airflow/providers/edge3/migrations/versions/0001_3_0_0_create_edge_tables.py
+++
b/providers/edge3/src/airflow/providers/edge3/migrations/versions/0001_3_0_0_create_edge_tables.py
@@ -71,7 +71,11 @@ def upgrade() -> None:
sa.PrimaryKeyConstraint("dag_id", "task_id", "run_id", "map_index",
"try_number"),
if_not_exists=True,
)
- op.create_index("rj_order", "edge_job", ["state", "queued_dttm", "queue"],
if_not_exists=True)
+ bind = op.get_bind()
+ inspector = sa.inspect(bind)
+ existing_indexes = {idx["name"] for idx in
inspector.get_indexes("edge_job")}
+ if "rj_order" not in existing_indexes:
+ op.create_index("rj_order", "edge_job", ["state", "queued_dttm",
"queue"])
op.create_table(
"edge_logs",
sa.Column("dag_id", sa.String(length=250), nullable=False),
diff --git a/providers/edge3/src/airflow/providers/edge3/models/db.py
b/providers/edge3/src/airflow/providers/edge3/models/db.py
index 1207dcd704c..3ff3dd84325 100644
--- a/providers/edge3/src/airflow/providers/edge3/models/db.py
+++ b/providers/edge3/src/airflow/providers/edge3/models/db.py
@@ -71,16 +71,22 @@ class EdgeDBManager(BaseDBManager):
def check_db_manager_config() -> None:
"""
- Warn if EdgeDBManager is not registered in the external_db_managers config.
+ Warn if EdgeDBManager is not registered to run DB migrations.
Should be called whenever the edge3 provider is active so operators are
alerted
early if the required database configuration is missing.
"""
from airflow.configuration import conf
+ from airflow.providers_manager import ProvidersManager
fqcn = f"{EdgeDBManager.__module__}.{EdgeDBManager.__name__}"
+
+ # Check explicitly configured managers
configured = conf.get("database", "external_db_managers", fallback="")
- registered = [m.strip() for m in configured.split(",") if m.strip()]
+ registered = {m.strip() for m in configured.split(",") if m.strip()}
+ # Also check auto-discovered managers from installed providers
+ registered |= set(ProvidersManager().db_managers)
+
if fqcn not in registered:
warnings.warn(
f"EdgeDBManager is not configured. Add '{fqcn}' to "
diff --git a/providers/edge3/tests/unit/edge3/models/test_db.py
b/providers/edge3/tests/unit/edge3/models/test_db.py
index 2ec969dc0c3..4424c4b1e59 100644
--- a/providers/edge3/tests/unit/edge3/models/test_db.py
+++ b/providers/edge3/tests/unit/edge3/models/test_db.py
@@ -44,7 +44,7 @@ class TestEdgeDBManager:
from airflow.providers.edge3.models.db import EdgeDBManager
run_db_manager = RunDBManager()
- assert run_db_manager._managers == [EdgeDBManager]
+ assert EdgeDBManager in run_db_manager._managers
@conf_vars(
{
@@ -247,24 +247,30 @@ class TestCheckDbManagerConfig:
pytestmark: list = [] # no db_test needed — purely config-based
- def test_warns_when_not_configured(self):
- """Warning is emitted when EdgeDBManager is absent from
external_db_managers."""
+ @mock.patch("airflow.providers_manager.ProvidersManager")
+ def test_warns_when_not_configured(self, mock_pm):
+ """Warning is emitted when EdgeDBManager is absent from
external_db_managers and not discovered."""
+ mock_pm.return_value.db_managers = []
from airflow.providers.edge3.models.db import check_db_manager_config
with conf_vars({("database", "external_db_managers"): ""}):
with pytest.warns(UserWarning, match="EdgeDBManager is not
configured"):
check_db_manager_config()
- def test_warns_when_other_manager_configured(self):
+ @mock.patch("airflow.providers_manager.ProvidersManager")
+ def test_warns_when_other_manager_configured(self, mock_pm):
"""Warning is emitted when a different manager is configured but not
EdgeDBManager."""
+ mock_pm.return_value.db_managers = []
from airflow.providers.edge3.models.db import check_db_manager_config
with conf_vars({("database", "external_db_managers"):
"some.other.DBManager"}):
with pytest.warns(UserWarning, match="EdgeDBManager is not
configured"):
check_db_manager_config()
- def test_no_warn_when_configured(self):
+ @mock.patch("airflow.providers_manager.ProvidersManager")
+ def test_no_warn_when_configured(self, mock_pm):
"""No warning when EdgeDBManager is properly configured."""
+ mock_pm.return_value.db_managers = []
from airflow.providers.edge3.models.db import check_db_manager_config
with conf_vars(
@@ -276,8 +282,10 @@ class TestCheckDbManagerConfig:
warnings.simplefilter("error")
check_db_manager_config() # must not raise
- def test_no_warn_when_configured_among_multiple(self):
+ @mock.patch("airflow.providers_manager.ProvidersManager")
+ def test_no_warn_when_configured_among_multiple(self, mock_pm):
"""No warning when EdgeDBManager appears alongside other managers."""
+ mock_pm.return_value.db_managers = []
from airflow.providers.edge3.models.db import check_db_manager_config
with conf_vars(
@@ -290,3 +298,14 @@ class TestCheckDbManagerConfig:
with warnings.catch_warnings():
warnings.simplefilter("error")
check_db_manager_config() # must not raise
+
+ @mock.patch("airflow.providers_manager.ProvidersManager")
+ def test_no_warn_when_discovered(self, mock_pm):
+ """No warning when EdgeDBManager is auto-discovered via
ProvidersManager."""
+ mock_pm.return_value.db_managers =
["airflow.providers.edge3.models.db.EdgeDBManager"]
+ from airflow.providers.edge3.models.db import check_db_manager_config
+
+ with conf_vars({("database", "external_db_managers"): ""}):
+ with warnings.catch_warnings():
+ warnings.simplefilter("error")
+ check_db_manager_config() # must not raise
diff --git
a/providers/edge3/tests/unit/edge3/plugins/test_edge_executor_plugin.py
b/providers/edge3/tests/unit/edge3/plugins/test_edge_executor_plugin.py
index 475e6e49158..2f06bb9c2d5 100644
--- a/providers/edge3/tests/unit/edge3/plugins/test_edge_executor_plugin.py
+++ b/providers/edge3/tests/unit/edge3/plugins/test_edge_executor_plugin.py
@@ -49,7 +49,11 @@ def test_plugin_active_apiserver():
# create dist folder if not built locally
(Path(edge_executor_plugin.__file__).parent / "www" /
"dist").mkdir(parents=True, exist_ok=True)
- with conf_vars({("edge", "api_enabled"): "true"}), patch("sys.argv",
mock_cli):
+ with (
+ conf_vars({("edge", "api_enabled"): "true"}),
+ patch("sys.argv", mock_cli),
+ patch("airflow.providers.edge3.models.db.check_db_manager_config"),
+ ):
importlib.reload(edge_executor_plugin)
from airflow.providers.edge3.plugins.edge_executor_plugin import (
@@ -68,7 +72,10 @@ def test_plugin_active_apiserver():
@patch("sys.argv", ["airflow", "some-other-command"])
def test_plugin_active_non_apiserver():
- with conf_vars({("edge", "api_enabled"): "true"}):
+ with (
+ conf_vars({("edge", "api_enabled"): "true"}),
+ patch("airflow.providers.edge3.models.db.check_db_manager_config"),
+ ):
importlib.reload(edge_executor_plugin)
from airflow.providers.edge3.plugins.edge_executor_plugin import (
diff --git a/providers/fab/provider.yaml b/providers/fab/provider.yaml
index ec2bc24900a..ad24ec1ad6d 100644
--- a/providers/fab/provider.yaml
+++ b/providers/fab/provider.yaml
@@ -266,5 +266,8 @@ config:
auth-managers:
- airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager
+db-managers:
+ - airflow.providers.fab.auth_manager.models.db.FABDBManager
+
cli:
- airflow.providers.fab.cli.definition.get_fab_cli_commands
diff --git a/providers/fab/src/airflow/providers/fab/get_provider_info.py
b/providers/fab/src/airflow/providers/fab/get_provider_info.py
index a7ab9325274..58923dec67d 100644
--- a/providers/fab/src/airflow/providers/fab/get_provider_info.py
+++ b/providers/fab/src/airflow/providers/fab/get_provider_info.py
@@ -188,5 +188,6 @@ def get_provider_info():
}
},
"auth-managers":
["airflow.providers.fab.auth_manager.fab_auth_manager.FabAuthManager"],
+ "db-managers":
["airflow.providers.fab.auth_manager.models.db.FABDBManager"],
"cli": ["airflow.providers.fab.cli.definition.get_fab_cli_commands"],
}
diff --git
a/providers/fab/src/airflow/providers/fab/migrations/versions/0000_1_4_0_create_ab_tables_if_missing.py
b/providers/fab/src/airflow/providers/fab/migrations/versions/0000_1_4_0_create_ab_tables_if_missing.py
index a7ad1301c4a..b7c7bdc0923 100644
---
a/providers/fab/src/airflow/providers/fab/migrations/versions/0000_1_4_0_create_ab_tables_if_missing.py
+++
b/providers/fab/src/airflow/providers/fab/migrations/versions/0000_1_4_0_create_ab_tables_if_missing.py
@@ -138,9 +138,13 @@ def upgrade() -> None:
sa.UniqueConstraint("group_id", "role_id",
name=op.f("ab_group_role_group_id_role_id_uq")),
if_not_exists=True,
)
- with op.batch_alter_table("ab_group_role", schema=None) as batch_op:
- batch_op.create_index("idx_group_id", ["group_id"], unique=False,
if_not_exists=True)
- batch_op.create_index("idx_group_role_id", ["role_id"], unique=False,
if_not_exists=True)
+ bind = op.get_bind()
+ inspector = sa.inspect(bind)
+ existing = {idx["name"] for idx in inspector.get_indexes("ab_group_role")}
+ if "idx_group_id" not in existing:
+ op.create_index("idx_group_id", "ab_group_role", ["group_id"],
unique=False)
+ if "idx_group_role_id" not in existing:
+ op.create_index("idx_group_role_id", "ab_group_role", ["role_id"],
unique=False)
op.create_table(
"ab_permission_view",
@@ -174,9 +178,11 @@ def upgrade() -> None:
sa.UniqueConstraint("user_id", "group_id",
name=op.f("ab_user_group_user_id_group_id_uq")),
if_not_exists=True,
)
- with op.batch_alter_table("ab_user_group", schema=None) as batch_op:
- batch_op.create_index("idx_user_group_id", ["group_id"], unique=False,
if_not_exists=True)
- batch_op.create_index("idx_user_id", ["user_id"], unique=False,
if_not_exists=True)
+ existing = {idx["name"] for idx in inspector.get_indexes("ab_user_group")}
+ if "idx_user_group_id" not in existing:
+ op.create_index("idx_user_group_id", "ab_user_group", ["group_id"],
unique=False)
+ if "idx_user_id" not in existing:
+ op.create_index("idx_user_id", "ab_user_group", ["user_id"],
unique=False)
op.create_table(
"ab_user_role",
diff --git a/providers/fab/tests/unit/fab/auth_manager/test_fab_auth_manager.py
b/providers/fab/tests/unit/fab/auth_manager/test_fab_auth_manager.py
index c47d02dd5a4..0e3bee5ed82 100644
--- a/providers/fab/tests/unit/fab/auth_manager/test_fab_auth_manager.py
+++ b/providers/fab/tests/unit/fab/auth_manager/test_fab_auth_manager.py
@@ -936,6 +936,7 @@ class TestFabAuthManager:
@conf_vars(
{("database", "external_db_managers"):
"airflow.providers.fab.auth_manager.models.db.FABDBManager"}
)
[email protected]("airflow.providers_manager.ProvidersManager")
@mock.patch("airflow.providers.fab.auth_manager.models.db.FABDBManager")
@mock.patch("airflow.utils.db.create_global_lock", new=MagicMock)
@mock.patch("airflow.utils.db.drop_airflow_models")
@@ -948,8 +949,10 @@ def test_resetdb(
mock_drop_moved,
mock_drop_airflow,
mock_fabdb_manager,
+ mock_pm,
skip_init,
):
+ mock_pm.return_value.db_managers = []
# Mock as non-MySQL to use the simpler PostgreSQL/SQLite path
mock_engine.dialect.name = "postgresql"
mock_connect = mock_engine.connect.return_value
diff --git a/providers/fab/tests/unit/fab/db_manager/test_fab_db_manager.py
b/providers/fab/tests/unit/fab/db_manager/test_fab_db_manager.py
index 606b046ea22..3e8158512c2 100644
--- a/providers/fab/tests/unit/fab/db_manager/test_fab_db_manager.py
+++ b/providers/fab/tests/unit/fab/db_manager/test_fab_db_manager.py
@@ -38,7 +38,7 @@ class TestRunDBManagerWithFab:
from airflow.providers.fab.auth_manager.models.db import FABDBManager
run_db_manager = RunDBManager()
- assert run_db_manager._managers == [FABDBManager]
+ assert FABDBManager in run_db_manager._managers
@conf_vars(
{("database", "external_db_managers"):
"airflow.providers.fab.auth_manager.models.db.FABDBManager"}