This is an automated email from the ASF dual-hosted git repository.
amoghrajesh 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 9ebc2644741 Revert "Secrets backends order updated (#70681)" (#73891)
9ebc2644741 is described below
commit 9ebc264474116c3f190e68895952247071b8f114
Author: Amogh Desai <[email protected]>
AuthorDate: Tue Sep 29 14:41:25 2026 +0530
Revert "Secrets backends order updated (#70681)" (#73891)
This reverts commit 5428b3b995bcc94aea572a03fc35dc8a82fd2c15.
---
.../security/secrets/secrets-backend/index.rst | 23 +---
airflow-core/newsfragments/70681.significant.rst | 7 --
.../api_fastapi/core_api/openapi/_private_ui.yaml | 98 -----------------
.../api_fastapi/core_api/routes/ui/config.py | 45 +-------
.../src/airflow/config_templates/config.yml | 34 ------
airflow-core/src/airflow/configuration.py | 7 +-
airflow-core/src/airflow/secrets/__init__.py | 4 +-
airflow-core/src/airflow/secrets/base_secrets.py | 5 +-
.../src/airflow/ui/openapi-gen/queries/common.ts | 6 -
.../ui/openapi-gen/queries/ensureQueryData.ts | 10 --
.../src/airflow/ui/openapi-gen/queries/prefetch.ts | 10 --
.../src/airflow/ui/openapi-gen/queries/queries.ts | 10 --
.../src/airflow/ui/openapi-gen/queries/suspense.ts | 10 --
.../ui/openapi-gen/requests/services.gen.ts | 24 +---
.../airflow/ui/openapi-gen/requests/types.gen.ts | 29 -----
.../airflow/ui/public/i18n/locales/en/admin.json | 2 -
.../src/airflow/ui/src/components/StatsCard.tsx | 2 +-
.../ui/src/pages/Variables/BackendsOrderCard.tsx | 45 --------
.../ui/src/pages/Variables/BackendsOrderModal.tsx | 64 -----------
.../airflow/ui/src/pages/Variables/Variables.tsx | 2 -
airflow-core/tests/unit/always/test_secrets.py | 121 ---------------------
.../api_fastapi/core_api/routes/ui/test_config.py | 62 -----------
.../configuration/secrets_backends.py | 88 ---------------
task-sdk/src/airflow/sdk/configuration.py | 10 +-
.../airflow/sdk/execution_time/secrets/__init__.py | 9 +-
.../src/airflow/sdk/execution_time/supervisor.py | 3 +-
.../tests/task_sdk/execution_time/test_context.py | 13 ++-
.../tests/task_sdk/execution_time/test_secrets.py | 3 +-
28 files changed, 30 insertions(+), 716 deletions(-)
diff --git a/airflow-core/docs/security/secrets/secrets-backend/index.rst
b/airflow-core/docs/security/secrets/secrets-backend/index.rst
index 45ea4944339..029dadcfb87 100644
--- a/airflow-core/docs/security/secrets/secrets-backend/index.rst
+++ b/airflow-core/docs/security/secrets/secrets-backend/index.rst
@@ -39,15 +39,13 @@ When looking up a connection/variable, by default Airflow
will search environmen
database second.
If you enable an alternative secrets backend, it will be searched first,
followed by environment variables,
-then metastore. Though, in some alternative secrets backend you might have
+then metastore. This search ordering is not configurable. Though, in some
alternative secrets backend you might have
the option to filter which connection/variable/config is searched in the
secret backend. Please look at the
documentation of the secret backend you are using to see if such option is
available.
On the other hand, if a workers secrets backend is defined, the order of
lookup has higher priority for the workers secrets
backend and then the secrets backend.
-The secrets backends search ordering is also configurable via the
configuration option ``[secrets]backends_order``.
-
.. warning::
When using environment variables or an alternative secrets backend to
store secrets or variables, it is possible to create key collisions.
@@ -66,21 +64,12 @@ The ``[secrets]`` section has the following options:
[secrets]
backend =
backend_kwargs =
- backends_order =
Set ``backend`` to the fully qualified class name of the backend you want to
enable.
You can provide ``backend_kwargs`` with json and it will be passed as kwargs
to the ``__init__`` method of
your secrets backend.
-``backends_order`` is a comma-separated list of secret backends. These
backends will be used in the order they are specified.
-Please note that the ``environment_variable`` and ``metastore`` are required
values and cannot be removed
-from the list. Supported values are:
-
-* ``custom``: Custom secret backend specified in the ``secrets[backend]``
configuration option.
-* ``environment_variable``: Standard environment variable backend
``airflow.secrets.environment_variables.EnvironmentVariablesBackend``.
-* ``metastore``: Standard metastore backend
``airflow.secrets.metastore.MetastoreBackend``.
-
If you want to check which secret backend is currently set, you can use
``airflow config get-value secrets backend`` command as in
the example below.
@@ -123,21 +112,13 @@ configure separate secrets backend for workers, you can
do that using:
[workers]
secrets_backend =
secrets_backend_kwargs =
- backends_order =
+
Set ``secrets_backend`` to the fully qualified class name of the backend you
want to enable.
You can provide ``secrets_backend_kwargs`` with json and it will be passed as
kwargs to the ``__init__`` method of
your secrets backend for the workers.
-``backends_order`` is a comma-separated list of secret backends for workers.
These backends will be used in the order they are specified.
-Please note that the ``environment_variable`` and ``execution_api`` are
required values and cannot be removed
-from the list. Supported values are:
-
-* ``custom``: Custom secret backend specified in the
``workers[secrets_backend]`` configuration option.
-* ``environment_variable``: Standard environment variable backend
``airflow.secrets.environment_variables.EnvironmentVariablesBackend``.
-* ``execution_api``: Standard execution_api backend
``airflow.sdk.execution_time.secrets.execution_api.ExecutionAPISecretsBackend``.
-
If you want to check which secret backend is currently set, you can use
``airflow config get-value workers secrets_backend`` command as in
the example below.
diff --git a/airflow-core/newsfragments/70681.significant.rst
b/airflow-core/newsfragments/70681.significant.rst
deleted file mode 100644
index 8cf2773d5fc..00000000000
--- a/airflow-core/newsfragments/70681.significant.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-Configurable secrets backend lookup order in Core and Workers
-
-Airflow now allows configuring the lookup order of secret backends via two new
configuration options:
-- ``[secrets] backends_order``: Controls lookup order for core components
(supports ``custom``, ``environment_variable``, and ``metastore``).
-- ``[workers] backends_order``: Controls lookup order on Task SDK workers
(supports ``custom``, ``environment_variable``, and ``execution_api``).
-
-The configured order can also be inspected in the UI on the Variables page and
via the ``GET /ui/backends_order`` endpoint. Default values preserve existing
behavior (``custom,environment_variable,metastore`` and
``custom,environment_variable,execution_api``).
diff --git
a/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml
b/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml
index 1681b462b37..66032afd609 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml
+++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/_private_ui.yaml
@@ -474,52 +474,6 @@ paths:
security:
- OAuth2PasswordBearer: []
- HTTPBearer: []
- /ui/backends_order:
- get:
- tags:
- - Config
- summary: Get Backends Order Value
- operationId: get_backends_order_value
- security:
- - OAuth2PasswordBearer: []
- - HTTPBearer: []
- parameters:
- - name: accept
- in: header
- required: false
- schema:
- type: string
- enum:
- - application/json
- - text/plain
- - '*/*'
- default: '*/*'
- title: Accept
- responses:
- '200':
- description: Successful Response
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/Config'
- '404':
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/HTTPExceptionResponse'
- description: Not Found
- '406':
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/HTTPExceptionResponse'
- description: Not Acceptable
- '422':
- description: Validation Error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/HTTPValidationError'
/ui/connections/hook_meta:
get:
tags:
@@ -2904,41 +2858,6 @@ components:
- count
title: CalendarTimeRangeResponse
description: Represents a summary of DAG runs for a specific calendar
time range.
- Config:
- properties:
- sections:
- items:
- $ref: '#/components/schemas/ConfigSection'
- type: array
- title: Sections
- additionalProperties: false
- type: object
- required:
- - sections
- title: Config
- description: List of config sections with their options.
- ConfigOption:
- properties:
- key:
- type: string
- title: Key
- value:
- anyOf:
- - type: string
- - prefixItems:
- - type: string
- - type: string
- type: array
- maxItems: 2
- minItems: 2
- title: Value
- additionalProperties: false
- type: object
- required:
- - key
- - value
- title: ConfigOption
- description: Config option.
ConfigResponse:
properties:
fallback_page_limit:
@@ -3006,23 +2925,6 @@ components:
- multi_team
title: ConfigResponse
description: configuration serializer.
- ConfigSection:
- properties:
- name:
- type: string
- title: Name
- options:
- items:
- $ref: '#/components/schemas/ConfigOption'
- type: array
- title: Options
- additionalProperties: false
- type: object
- required:
- - name
- - options
- title: ConfigSection
- description: Config Section Schema.
ConnectionHookFieldBehavior:
properties:
hidden:
diff --git a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/config.py
b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/config.py
index 5f2aa7a046c..7a93583875f 100644
--- a/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/config.py
+++ b/airflow-core/src/airflow/api_fastapi/core_api/routes/ui/config.py
@@ -19,23 +19,13 @@ from __future__ import annotations
from json import loads
from typing import Any
-from fastapi import Depends, HTTPException, status
+from fastapi import Depends, status
-from airflow.api_fastapi.common.headers import HeaderAcceptJsonOrText
from airflow.api_fastapi.common.router import AirflowRouter
from airflow.api_fastapi.common.types import UIAlert
-from airflow.api_fastapi.core_api.datamodels.config import (
- Config,
- ConfigOption,
- ConfigSection,
-)
from airflow.api_fastapi.core_api.datamodels.ui.config import ConfigResponse
from airflow.api_fastapi.core_api.openapi.exceptions import
create_openapi_http_exception_doc
-from airflow.api_fastapi.core_api.security import
requires_access_configuration, requires_authenticated
-from airflow.api_fastapi.core_api.services.public.config import (
- _check_expose_config,
- _response_based_on_accept,
-)
+from airflow.api_fastapi.core_api.security import requires_authenticated
from airflow.configuration import conf
from airflow.settings import DASHBOARD_UIALERTS
from airflow.utils.log.log_reader import TaskLogReader
@@ -84,34 +74,3 @@ def get_configs() -> ConfigResponse:
config.update({key: value for key, value in additional_config.items()})
return ConfigResponse.model_validate(config)
-
-
-@config_router.get(
- "/backends_order",
- responses={
- **create_openapi_http_exception_doc(
- [
- status.HTTP_404_NOT_FOUND,
- status.HTTP_406_NOT_ACCEPTABLE,
- ]
- ),
- },
- response_model=Config,
- dependencies=[Depends(requires_access_configuration("GET"))],
-)
-def get_backends_order_value(
- accept: HeaderAcceptJsonOrText,
-):
- _check_expose_config()
-
- section, option = "secrets", "backends_order"
- if not conf.has_option(section, option):
- raise HTTPException(
- status_code=status.HTTP_404_NOT_FOUND,
- detail=f"Option [{section}/{option}] not found.",
- )
-
- value = conf.get(section, option)
-
- config = Config(sections=[ConfigSection(name=section,
options=[ConfigOption(key=option, value=value)])])
- return _response_based_on_accept(accept, config)
diff --git a/airflow-core/src/airflow/config_templates/config.yml
b/airflow-core/src/airflow/config_templates/config.yml
index 54710d9557d..4d3677a1d4a 100644
--- a/airflow-core/src/airflow/config_templates/config.yml
+++ b/airflow-core/src/airflow/config_templates/config.yml
@@ -1600,22 +1600,6 @@ secrets:
sensitive: true
example: ~
default: ""
- backends_order:
- description: |
- .. note:: |experimental|
-
- Comma-separated list of secret backends. These backends will be used
in the order they are specified.
- Please note that the ``environment_variable`` and ``metastore`` are
required values and cannot be
- removed from the list. Supported values are:
-
- * ``custom``: Custom secret backend specified in the
``secrets[backend]`` configuration option.
- * ``environment_variable``: Standard environment variable backend
-
``airflow.secrets.environment_variables.EnvironmentVariablesBackend``.
- * ``metastore``: Standard metastore backend
``airflow.secrets.metastore.MetastoreBackend``.
- version_added: 3.3.0
- type: string
- example: ~
- default: "custom,environment_variable,metastore"
use_cache:
description: |
.. note:: |experimental|
@@ -2105,24 +2089,6 @@ workers:
type: string
example: "mypackage.state.S3StateBackend"
default: ""
- backends_order:
- description: |
- .. note:: |experimental|
-
- Comma-separated list of secret backends for workers. These backends
will be used in the order they are
- specified. Please note that the ``environment_variable`` and
``execution_api`` are required values and
- cannot be removed from the list. Supported values are:
-
- * ``custom``: Custom secret backend specified in the
``workers[secrets_backend]`` configuration
- option.
- * ``environment_variable``: Standard environment variable backend
-
``airflow.secrets.environment_variables.EnvironmentVariablesBackend``.
- * ``execution_api``: Standard execution_api backend
-
``airflow.sdk.execution_time.secrets.execution_api.ExecutionAPISecretsBackend``.
- version_added: 3.3.0
- type: string
- example: ~
- default: "custom,environment_variable,execution_api"
min_heartbeat_interval:
description: |
The minimum interval (in seconds) at which the worker checks the task
instance's
diff --git a/airflow-core/src/airflow/configuration.py
b/airflow-core/src/airflow/configuration.py
index 3e88882ba12..f9dd0af27b1 100644
--- a/airflow-core/src/airflow/configuration.py
+++ b/airflow-core/src/airflow/configuration.py
@@ -41,7 +41,6 @@ from airflow._shared.configuration.parser import (
AirflowConfigParser as _SharedAirflowConfigParser,
configure_parser_from_configuration_description,
)
-from airflow._shared.configuration.secrets_backends import Backend,
sorted_backends
from airflow._shared.module_loading import import_string
from airflow.exceptions import AirflowConfigException, RemovedInAirflow4Warning
from airflow.secrets import DEFAULT_SECRETS_SEARCH_PATH
@@ -761,7 +760,7 @@ def initialize_secrets_backends(
from airflow.models import Connection
custom_secret_backend._set_connection_class(Connection)
- backend_list.append((Backend.CUSTOM, custom_secret_backend))
+ backend_list.append(custom_secret_backend)
for class_name in default_backends:
from airflow.models import Connection
@@ -769,9 +768,9 @@ def initialize_secrets_backends(
secrets_backend_cls = import_string(class_name)
backend = secrets_backend_cls()
backend._set_connection_class(Connection)
- backend_list.append((Backend.from_path(class_name), backend))
+ backend_list.append(backend)
- return sorted_backends(conf, backend_list, worker_mode)
+ return backend_list
def initialize_auth_manager() -> BaseAuthManager:
diff --git a/airflow-core/src/airflow/secrets/__init__.py
b/airflow-core/src/airflow/secrets/__init__.py
index 3295a55af92..f9b8e20ba0c 100644
--- a/airflow-core/src/airflow/secrets/__init__.py
+++ b/airflow-core/src/airflow/secrets/__init__.py
@@ -61,11 +61,9 @@ def __getattr__(name):
return DEFAULT_SECRETS_SEARCH_PATH_WORKERS
except (ImportError, AttributeError):
- from airflow._shared.configuration import secrets_backends
-
# Back-compat for older Task SDK clients
return [
- secrets_backends.ENVIRONMENT_VARIABLE_BACKEND_PATH,
+
"airflow.secrets.environment_variables.EnvironmentVariablesBackend",
]
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
diff --git a/airflow-core/src/airflow/secrets/base_secrets.py
b/airflow-core/src/airflow/secrets/base_secrets.py
index b74b4e05e0c..939d993cfcc 100644
--- a/airflow-core/src/airflow/secrets/base_secrets.py
+++ b/airflow-core/src/airflow/secrets/base_secrets.py
@@ -16,7 +16,6 @@
# under the License.
from __future__ import annotations
-from airflow._shared.configuration import secrets_backends
from airflow._shared.secrets_backend.base import BaseSecretsBackend as
_BaseSecretsBackend
@@ -35,6 +34,6 @@ class BaseSecretsBackend(_BaseSecretsBackend):
# Server side default secrets backend search path used by server components
(scheduler, API server)
DEFAULT_SECRETS_SEARCH_PATH = [
- secrets_backends.ENVIRONMENT_VARIABLE_BACKEND_PATH,
- secrets_backends.METASTORE_BACKEND_PATH,
+ "airflow.secrets.environment_variables.EnvironmentVariablesBackend",
+ "airflow.secrets.metastore.MetastoreBackend",
]
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
index 06bc2d3c5ed..574871897ab 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
@@ -337,12 +337,6 @@ export type ConfigServiceGetConfigsDefaultResponse =
Awaited<ReturnType<typeof C
export type ConfigServiceGetConfigsQueryResult<TData =
ConfigServiceGetConfigsDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
export const useConfigServiceGetConfigsKey = "ConfigServiceGetConfigs";
export const UseConfigServiceGetConfigsKeyFn = (queryKey?: Array<unknown>) =>
[useConfigServiceGetConfigsKey, ...(queryKey ?? [])];
-export type ConfigServiceGetBackendsOrderValueDefaultResponse =
Awaited<ReturnType<typeof ConfigService.getBackendsOrderValue>>;
-export type ConfigServiceGetBackendsOrderValueQueryResult<TData =
ConfigServiceGetBackendsOrderValueDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
-export const useConfigServiceGetBackendsOrderValueKey =
"ConfigServiceGetBackendsOrderValue";
-export const UseConfigServiceGetBackendsOrderValueKeyFn = ({ accept }: {
- accept?: "application/json" | "text/plain" | "*/*";
-} = {}, queryKey?: Array<unknown>) =>
[useConfigServiceGetBackendsOrderValueKey, ...(queryKey ?? [{ accept }])];
export type DagWarningServiceListDagWarningsDefaultResponse =
Awaited<ReturnType<typeof DagWarningService.listDagWarnings>>;
export type DagWarningServiceListDagWarningsQueryResult<TData =
DagWarningServiceListDagWarningsDefaultResponse, TError = unknown> =
UseQueryResult<TData, TError>;
export const useDagWarningServiceListDagWarningsKey =
"DagWarningServiceListDagWarnings";
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
index 2570e9dd603..01983ce4e99 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/ensureQueryData.ts
@@ -669,16 +669,6 @@ export const ensureUseConfigServiceGetConfigValueData =
(queryClient: QueryClien
*/
export const ensureUseConfigServiceGetConfigsData = (queryClient: QueryClient)
=> queryClient.ensureQueryData({ queryKey:
Common.UseConfigServiceGetConfigsKeyFn(), queryFn: () =>
ConfigService.getConfigs() });
/**
-* Get Backends Order Value
-* @param data The data for the request.
-* @param data.accept
-* @returns Config Successful Response
-* @throws ApiError
-*/
-export const ensureUseConfigServiceGetBackendsOrderValueData = (queryClient:
QueryClient, { accept }: {
- accept?: "application/json" | "text/plain" | "*/*";
-} = {}) => queryClient.ensureQueryData({ queryKey:
Common.UseConfigServiceGetBackendsOrderValueKeyFn({ accept }), queryFn: () =>
ConfigService.getBackendsOrderValue({ accept }) });
-/**
* List Dag Warnings
* Get a list of Dag warnings.
* @param data The data for the request.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
index 769d0956439..501689dc55d 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
@@ -669,16 +669,6 @@ export const prefetchUseConfigServiceGetConfigValue =
(queryClient: QueryClient,
*/
export const prefetchUseConfigServiceGetConfigs = (queryClient: QueryClient)
=> queryClient.prefetchQuery({ queryKey:
Common.UseConfigServiceGetConfigsKeyFn(), queryFn: () =>
ConfigService.getConfigs() });
/**
-* Get Backends Order Value
-* @param data The data for the request.
-* @param data.accept
-* @returns Config Successful Response
-* @throws ApiError
-*/
-export const prefetchUseConfigServiceGetBackendsOrderValue = (queryClient:
QueryClient, { accept }: {
- accept?: "application/json" | "text/plain" | "*/*";
-} = {}) => queryClient.prefetchQuery({ queryKey:
Common.UseConfigServiceGetBackendsOrderValueKeyFn({ accept }), queryFn: () =>
ConfigService.getBackendsOrderValue({ accept }) });
-/**
* List Dag Warnings
* Get a list of Dag warnings.
* @param data The data for the request.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
index 85d497cc328..4951fc96970 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
@@ -669,16 +669,6 @@ export const useConfigServiceGetConfigValue = <TData =
Common.ConfigServiceGetCo
*/
export const useConfigServiceGetConfigs = <TData =
Common.ConfigServiceGetConfigsDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>(queryKey?: TQueryKey, options?:
Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) =>
useQuery<TData, TError>({ queryKey:
Common.UseConfigServiceGetConfigsKeyFn(queryKey), queryFn: () =>
ConfigService.getConfigs() as TData, ...options });
/**
-* Get Backends Order Value
-* @param data The data for the request.
-* @param data.accept
-* @returns Config Successful Response
-* @throws ApiError
-*/
-export const useConfigServiceGetBackendsOrderValue = <TData =
Common.ConfigServiceGetBackendsOrderValueDefaultResponse, TError = unknown,
TQueryKey extends Array<unknown> = unknown[]>({ accept }: {
- accept?: "application/json" | "text/plain" | "*/*";
-} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey:
Common.UseConfigServiceGetBackendsOrderValueKeyFn({ accept }, queryKey),
queryFn: () => ConfigService.getBackendsOrderValue({ accept }) as TData,
...options });
-/**
* List Dag Warnings
* Get a list of Dag warnings.
* @param data The data for the request.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
index 575195e947f..6c91b91e143 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
@@ -669,16 +669,6 @@ export const useConfigServiceGetConfigValueSuspense =
<TData = Common.ConfigServ
*/
export const useConfigServiceGetConfigsSuspense = <TData =
Common.ConfigServiceGetConfigsDefaultResponse, TError = unknown, TQueryKey
extends Array<unknown> = unknown[]>(queryKey?: TQueryKey, options?:
Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) =>
useSuspenseQuery<TData, TError>({ queryKey:
Common.UseConfigServiceGetConfigsKeyFn(queryKey), queryFn: () =>
ConfigService.getConfigs() as TData, ...options });
/**
-* Get Backends Order Value
-* @param data The data for the request.
-* @param data.accept
-* @returns Config Successful Response
-* @throws ApiError
-*/
-export const useConfigServiceGetBackendsOrderValueSuspense = <TData =
Common.ConfigServiceGetBackendsOrderValueDefaultResponse, TError = unknown,
TQueryKey extends Array<unknown> = unknown[]>({ accept }: {
- accept?: "application/json" | "text/plain" | "*/*";
-} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>,
"queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey:
Common.UseConfigServiceGetBackendsOrderValueKeyFn({ accept }, queryKey),
queryFn: () => ConfigService.getBackendsOrderValue({ accept }) as TData,
...options });
-/**
* List Dag Warnings
* Get a list of Dag warnings.
* @param data The data for the request.
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
index 4bc00293075..d0a1a936ed9 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/services.gen.ts
@@ -3,7 +3,7 @@
import type { CancelablePromise } from './core/CancelablePromise';
import { OpenAPI } from './core/OpenAPI';
import { request as __request } from './core/request';
-import type { GetAssetsData, GetAssetsResponse, GetAssetAliasesData,
GetAssetAliasesResponse, GetAssetAliasData, GetAssetAliasResponse,
GetAssetEventsData, GetAssetEventsResponse, CreateAssetEventData,
CreateAssetEventResponse, MaterializeAssetData, MaterializeAssetResponse,
GetAssetQueuedEventsData, GetAssetQueuedEventsResponse,
DeleteAssetQueuedEventsData, DeleteAssetQueuedEventsResponse, GetAssetData,
GetAssetResponse, GetDagAssetQueuedEventsData, GetDagAssetQueuedEventsResponse,
Dele [...]
+import type { GetAssetsData, GetAssetsResponse, GetAssetAliasesData,
GetAssetAliasesResponse, GetAssetAliasData, GetAssetAliasResponse,
GetAssetEventsData, GetAssetEventsResponse, CreateAssetEventData,
CreateAssetEventResponse, MaterializeAssetData, MaterializeAssetResponse,
GetAssetQueuedEventsData, GetAssetQueuedEventsResponse,
DeleteAssetQueuedEventsData, DeleteAssetQueuedEventsResponse, GetAssetData,
GetAssetResponse, GetDagAssetQueuedEventsData, GetDagAssetQueuedEventsResponse,
Dele [...]
export class AssetService {
/**
@@ -1771,28 +1771,6 @@ export class ConfigService {
});
}
- /**
- * Get Backends Order Value
- * @param data The data for the request.
- * @param data.accept
- * @returns Config Successful Response
- * @throws ApiError
- */
- public static getBackendsOrderValue(data: GetBackendsOrderValueData = {}):
CancelablePromise<GetBackendsOrderValueResponse> {
- return __request(OpenAPI, {
- method: 'GET',
- url: '/ui/backends_order',
- headers: {
- accept: data.accept
- },
- errors: {
- 404: 'Not Found',
- 406: 'Not Acceptable',
- 422: 'Validation Error'
- }
- });
- }
-
}
export class DagWarningService {
diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
index ce784736c7a..7e33899b2ea 100644
--- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
+++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts
@@ -3720,12 +3720,6 @@ export type GetConfigValueResponse = Config;
export type GetConfigsResponse = ConfigResponse;
-export type GetBackendsOrderValueData = {
- accept?: 'application/json' | 'text/plain' | '*/*';
-};
-
-export type GetBackendsOrderValueResponse = Config;
-
export type ListDagWarningsData = {
dagId?: string | null;
limit?: number;
@@ -6636,29 +6630,6 @@ export type $OpenApiTs = {
};
};
};
- '/ui/backends_order': {
- get: {
- req: GetBackendsOrderValueData;
- res: {
- /**
- * Successful Response
- */
- 200: Config;
- /**
- * Not Found
- */
- 404: HTTPExceptionResponse;
- /**
- * Not Acceptable
- */
- 406: HTTPExceptionResponse;
- /**
- * Validation Error
- */
- 422: HTTPValidationError;
- };
- };
- };
'/api/v2/dagWarnings': {
get: {
req: ListDagWarningsData;
diff --git a/airflow-core/src/airflow/ui/public/i18n/locales/en/admin.json
b/airflow-core/src/airflow/ui/public/i18n/locales/en/admin.json
index 6a45b05d0a4..ae0f534150e 100644
--- a/airflow-core/src/airflow/ui/public/i18n/locales/en/admin.json
+++ b/airflow-core/src/airflow/ui/public/i18n/locales/en/admin.json
@@ -148,7 +148,6 @@
},
"variables": {
"add": "Add $t(variables.variable_one)",
- "backendsOrder": "Secret backends order",
"columns": {
"isEncrypted": "Is Encrypted"
},
@@ -190,7 +189,6 @@
"upload": "Upload a JSON File",
"uploadPlaceholder": "Upload a JSON file containing variables (e.g.,
{\"key\": \"value\", ...})"
},
- "loading": "Loading...",
"noRowsMessage": "No variables found",
"searchPlaceholder": "Search Keys",
"variable_one": "Variable",
diff --git a/airflow-core/src/airflow/ui/src/components/StatsCard.tsx
b/airflow-core/src/airflow/ui/src/components/StatsCard.tsx
index 0780bcea67b..76955ea3448 100644
--- a/airflow-core/src/airflow/ui/src/components/StatsCard.tsx
+++ b/airflow-core/src/airflow/ui/src/components/StatsCard.tsx
@@ -38,7 +38,7 @@ export const StatsCard = ({
state,
}: {
readonly colorScheme: string;
- readonly count?: number;
+ readonly count: number;
readonly icon?: ReactNode;
readonly isLoading?: boolean;
readonly isRTL: boolean;
diff --git
a/airflow-core/src/airflow/ui/src/pages/Variables/BackendsOrderCard.tsx
b/airflow-core/src/airflow/ui/src/pages/Variables/BackendsOrderCard.tsx
deleted file mode 100644
index c20fd17cd24..00000000000
--- a/airflow-core/src/airflow/ui/src/pages/Variables/BackendsOrderCard.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-/*!
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import { Box, useDisclosure } from "@chakra-ui/react";
-import { useTranslation } from "react-i18next";
-import { LuSettings } from "react-icons/lu";
-
-import { StatsCard } from "src/components/StatsCard";
-
-import { BackendsOrderModal } from "./BackendsOrderModal";
-
-export const BackendsOrderCard = () => {
- const { i18n, t: translate } = useTranslation("admin");
- const isRTL = i18n.dir() === "rtl";
- const { onClose, onOpen, open } = useDisclosure();
-
- return (
- <Box alignItems="center" display="flex">
- <StatsCard
- colorScheme="gray"
- icon={<LuSettings />}
- isLoading={false}
- isRTL={isRTL}
- label={translate("variables.backendsOrder")}
- onClick={onOpen}
- />
- <BackendsOrderModal onClose={onClose} open={open} />
- </Box>
- );
-};
diff --git
a/airflow-core/src/airflow/ui/src/pages/Variables/BackendsOrderModal.tsx
b/airflow-core/src/airflow/ui/src/pages/Variables/BackendsOrderModal.tsx
deleted file mode 100644
index e13c7942013..00000000000
--- a/airflow-core/src/airflow/ui/src/pages/Variables/BackendsOrderModal.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-/*!
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-import { Heading, Text, HStack } from "@chakra-ui/react";
-import { useTranslation } from "react-i18next";
-import { LuSettings } from "react-icons/lu";
-
-import { useConfigServiceGetBackendsOrderValue } from "openapi/queries";
-
-import { Dialog } from "src/system-components";
-
-import { ErrorAlert } from "src/components/ErrorAlert";
-
-type BackendsOrderModalProps = {
- readonly onClose: () => void;
- readonly open: boolean;
-};
-
-export const BackendsOrderModal = ({ onClose, open }: BackendsOrderModalProps)
=> {
- const { t: translate } = useTranslation("admin");
- const { data, error, isLoading } =
useConfigServiceGetBackendsOrderValue(undefined, undefined, {
- enabled: open,
- });
- const backendsOrder = data?.sections[0]?.options[0]?.value ?? "";
-
- const onOpenChange = () => {
- onClose();
- };
-
- return (
- <Dialog.Root onOpenChange={onOpenChange} open={open}
scrollBehavior="inside" size="md">
- <Dialog.Content backdrop p={4}>
- <Dialog.Header display="flex" justifyContent="space-between">
- <HStack fontSize="xl">
- <LuSettings />
- <Heading size="md">{translate("variables.backendsOrder")}</Heading>
- </HStack>
- <Dialog.CloseTrigger />
- </Dialog.Header>
- <Dialog.Body>
- {Boolean(error) ? <ErrorAlert error={error} /> : null}
- <Text fontFamily="mono" fontSize="sm" whiteSpace="pre-wrap">
- {isLoading ? translate("variables.loading") : backendsOrder}
- </Text>
- </Dialog.Body>
- </Dialog.Content>
- </Dialog.Root>
- );
-};
diff --git a/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx
b/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx
index c408331ba7b..0c3048971fd 100644
--- a/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Variables/Variables.tsx
@@ -48,7 +48,6 @@ import { useConfig } from "src/queries/useConfig.tsx";
import { useDocumentTitle } from "src/utils";
import { TrimText } from "src/utils/TrimText";
-import { BackendsOrderCard } from "./BackendsOrderCard";
import DeleteVariablesButton from "./DeleteVariablesButton";
import ImportVariablesButton from "./ImportVariablesButton";
import AddVariableButton from "./ManageVariable/AddVariableButton";
@@ -203,7 +202,6 @@ export const Variables = () => {
onSelectAll={handleSelectAll}
selectedRows={selectedRows}
>
- <BackendsOrderCard />
<DataTable
columns={columns}
data={variables}
diff --git a/airflow-core/tests/unit/always/test_secrets.py
b/airflow-core/tests/unit/always/test_secrets.py
index 0e1b4c076dc..4d7371303b6 100644
--- a/airflow-core/tests/unit/always/test_secrets.py
+++ b/airflow-core/tests/unit/always/test_secrets.py
@@ -22,7 +22,6 @@ from unittest import mock
import pytest
from airflow.configuration import ensure_secrets_loaded,
initialize_secrets_backends
-from airflow.exceptions import AirflowConfigException
from airflow.models import Connection, Variable
from airflow.sdk import SecretCache
from airflow.sdk.exceptions import AirflowNotFoundException
@@ -118,126 +117,6 @@ class TestConnectionsFromSecrets:
with pytest.raises(AirflowNotFoundException, match=r"The conn_id
`_team___test_mysql` isn't defined"):
Connection.get_connection_from_secrets(conn_id="_team___test_mysql")
- @conf_vars(
- {
- (
- "secrets",
- "backend",
- ):
"airflow.providers.amazon.aws.secrets.systems_manager.SystemsManagerParameterStoreBackend",
- ("secrets", "backend_kwargs"): '{"connections_prefix": "/airflow",
"profile_name": null}',
- ("secrets", "backends_order"):
"custom,environment_variable,metastore",
- }
- )
- def test_backends_order(self):
- backends = ensure_secrets_loaded()
- backend_classes = [backend.__class__.__name__ for backend in backends]
- assert backend_classes == [
- "SystemsManagerParameterStoreBackend",
- "EnvironmentVariablesBackend",
- "MetastoreBackend",
- ]
-
- @pytest.mark.parametrize(
- ("backends_order", "expected_backends_order"),
- [
- pytest.param(
- "custom,environment_variable,execution_api",
- [
- "SystemsManagerParameterStoreBackend",
- "EnvironmentVariablesBackend",
- "ExecutionAPISecretsBackend",
- ],
- ),
- pytest.param(
- "environment_variable,execution_api,custom",
- [
- "EnvironmentVariablesBackend",
- "ExecutionAPISecretsBackend",
- "SystemsManagerParameterStoreBackend",
- ],
- ),
- pytest.param(
- "execution_api,environment_variable,custom",
- [
- "ExecutionAPISecretsBackend",
- "EnvironmentVariablesBackend",
- "SystemsManagerParameterStoreBackend",
- ],
- ),
- ],
- )
- def test_workers_backends_order_param(self, backends_order,
expected_backends_order):
- with conf_vars(
- {
- (
- "workers",
- "secrets_backend",
- ):
"airflow.providers.amazon.aws.secrets.systems_manager.SystemsManagerParameterStoreBackend",
- (
- "workers",
- "secrets_backend_kwargs",
- ): '{"connections_prefix": "/airflow", "profile_name": null}',
- ("workers", "backends_order"): backends_order,
- }
- ):
- backends = ensure_secrets_loaded(
- default_backends=[
-
"airflow.secrets.environment_variables.EnvironmentVariablesBackend",
-
"airflow.sdk.execution_time.secrets.execution_api.ExecutionAPISecretsBackend",
- ]
- )
- backend_classes = [backend.__class__.__name__ for backend in
backends]
- assert backend_classes == expected_backends_order
-
- @pytest.mark.parametrize(
- "backends_order",
- [
- pytest.param("custom,metastore",
id="no_environment_variable_backend"),
- pytest.param("environment_variable", id="no_metastore_backend"),
- pytest.param("metastore,environment_variable,unsupported",
id="unsupported_backend"),
- ],
- )
- def test_backends_order_invalid_cases(self, backends_order):
- with conf_vars({("secrets", "backends_order"): backends_order}):
- with pytest.raises(AirflowConfigException):
- ensure_secrets_loaded()
-
- @pytest.mark.parametrize(
- ("backends_order", "exc_msg"),
- [
- pytest.param(
- "custom,environment_variable",
- "The configuration option [workers]backends_order is
misconfigured. The following backend types are missing: ['execution_api']",
- id="no_execution_api_backend",
- ),
- pytest.param(
- "execution_api",
- "The configuration option [workers]backends_order is
misconfigured. The following backend types are missing:
['environment_variable']",
- id="no_environment_variable_backend",
- ),
- pytest.param(
- "custom",
- "The configuration option [workers]backends_order is
misconfigured. The following backend types are missing:
['environment_variable', 'execution_api']",
- id="no_environment_variable_and_execution_api_backend",
- ),
- pytest.param(
- "execution_api,environment_variable,unsupported",
- "The configuration option [workers]backends_order is
misconfigured. The following backend types are unsupported: ['unsupported']",
- id="unsupported_backend",
- ),
- ],
- )
- def test_workers_backends_order_invalid_cases(self, backends_order,
exc_msg):
- with conf_vars({("workers", "backends_order"): backends_order}):
- with pytest.raises(AirflowConfigException) as exc_info:
- ensure_secrets_loaded(
- default_backends=[
-
"airflow.secrets.environment_variables.EnvironmentVariablesBackend",
-
"airflow.sdk.execution_time.secrets.execution_api.ExecutionAPISecretsBackend",
- ]
- )
- assert exc_info.value.args[0] == exc_msg
-
@pytest.mark.db_test
class TestVariableFromSecrets:
diff --git
a/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_config.py
b/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_config.py
index ba583cbc828..b8a70a96d2e 100644
--- a/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_config.py
+++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/ui/test_config.py
@@ -150,17 +150,6 @@ def mock_config_data_css_only():
yield
[email protected]
-def mock_backends_order():
- with conf_vars(
- {
- ("api", "expose_config"): "True",
- ("secrets", "backends_order"):
"custom,environment_variable,metastore",
- }
- ):
- yield
-
-
class TestGetConfig:
def test_should_response_200(self, mock_config_data, test_client):
"""
@@ -206,54 +195,3 @@ class TestGetConfig:
assert theme["globalCss"] == {"button": {"text-transform":
"uppercase"}}
assert "icon" not in theme
assert "icon_dark_mode" not in theme
-
-
-class TestGetBackendsOrder:
- def test_should_respond_200_json(self, mock_backends_order, test_client):
- response = test_client.get("/backends_order", headers={"Accept":
"application/json"})
- assert response.status_code == 200
- assert response.json() == {
- "sections": [
- {
- "name": "secrets",
- "options": [
- {
- "key": "backends_order",
- "value": "custom,environment_variable,metastore",
- }
- ],
- }
- ]
- }
-
- def test_should_respond_200_text(self, mock_backends_order, test_client):
- response = test_client.get("/backends_order", headers={"Accept":
"text/plain"})
- assert response.status_code == 200
- assert response.text == "[secrets]\nbackends_order =
custom,environment_variable,metastore\n"
-
- @conf_vars({("api", "expose_config"): "True", ("secrets",
"backends_order"): None})
- def test_should_respond_404(self, test_client):
- response = test_client.get("/backends_order")
- assert response.status_code == 404
- assert response.json() == {"detail": "Option [secrets/backends_order]
not found."}
-
- def test_should_respond_401(self, unauthenticated_test_client):
- response = unauthenticated_test_client.get("/backends_order")
- assert response.status_code == 401
-
- def test_should_respond_406_not_acceptable(self, mock_backends_order,
test_client):
- response = test_client.get("/backends_order", headers={"Accept":
"text/html"})
- assert response.status_code == 406
- assert response.json() == {"detail": "Only application/json or
text/plain is supported"}
-
- def test_should_respond_403_unauthorized(self, mock_backends_order,
unauthorized_test_client):
- response = unauthorized_test_client.get("/backends_order")
- assert response.status_code == 403
-
- @conf_vars({("api", "expose_config"): "False"})
- def test_should_respond_403_expose_config_disabled(self, test_client):
- response = test_client.get("/backends_order")
- assert response.status_code == 403
- assert response.json() == {
- "detail": "Your Airflow administrator chose not to expose the
configuration, most likely for security reasons."
- }
diff --git
a/shared/configuration/src/airflow_shared/configuration/secrets_backends.py
b/shared/configuration/src/airflow_shared/configuration/secrets_backends.py
deleted file mode 100644
index 96bc0fa445e..00000000000
--- a/shared/configuration/src/airflow_shared/configuration/secrets_backends.py
+++ /dev/null
@@ -1,88 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-from __future__ import annotations
-
-import enum
-from typing import TYPE_CHECKING, TypeVar
-
-from .exceptions import AirflowConfigException
-
-if TYPE_CHECKING:
- from .parser import AirflowConfigParser
-
-
-_T = TypeVar("_T")
-
-
-ENVIRONMENT_VARIABLE_BACKEND_PATH =
"airflow.secrets.environment_variables.EnvironmentVariablesBackend"
-EXECUTION_API_BACKEND_PATH =
"airflow.sdk.execution_time.secrets.execution_api.ExecutionAPISecretsBackend"
-METASTORE_BACKEND_PATH = "airflow.secrets.metastore.MetastoreBackend"
-
-
-class Backend(enum.Enum):
- """Known secrets backends."""
-
- ENVIRONMENT_VARIABLE = "environment_variable"
- EXECUTION_API = "execution_api"
- CUSTOM = "custom"
- METASTORE = "metastore"
-
- @classmethod
- def from_path(cls, default_backend: str) -> Backend:
- if default_backend == ENVIRONMENT_VARIABLE_BACKEND_PATH:
- return cls.ENVIRONMENT_VARIABLE
- if default_backend == EXECUTION_API_BACKEND_PATH:
- return cls.EXECUTION_API
- if default_backend == METASTORE_BACKEND_PATH:
- return cls.METASTORE
-
- raise ValueError(f"Unknown module provided: {default_backend}")
-
-
-def _get_secrets_backend_order(
- conf: AirflowConfigParser, required_backends: list[Backend], worker_mode:
bool
-) -> list[Backend]:
- search_section = "workers" if worker_mode else "secrets"
- invalid_backends = []
- backends_order = []
- for backend in conf.getlist(search_section, "backends_order",
delimiter=","):
- try:
- backends_order.append(Backend(backend))
- except ValueError:
- invalid_backends.append(backend)
-
- if invalid_backends:
- raise AirflowConfigException(
- f"The configuration option [{search_section}]backends_order is
misconfigured. "
- f"The following backend types are unsupported: {invalid_backends}",
- )
-
- # backend is in use but its missing from ordering
- if missing_backends := [b.value for b in required_backends if b not in
backends_order]:
- raise AirflowConfigException(
- f"The configuration option [{search_section}]backends_order is
misconfigured. "
- f"The following backend types are missing: {missing_backends}",
- )
-
- return backends_order
-
-
-def sorted_backends(
- conf: AirflowConfigParser, backend_list: list[tuple[Backend, _T]],
worker_mode: bool
-) -> list[_T]:
- backends_order = _get_secrets_backend_order(conf, [b[0] for b in
backend_list], worker_mode)
- return [b[1] for b in sorted(backend_list, key=lambda e:
backends_order.index(e[0]))]
diff --git a/task-sdk/src/airflow/sdk/configuration.py
b/task-sdk/src/airflow/sdk/configuration.py
index 2ac25a731fe..e6bcf0ca429 100644
--- a/task-sdk/src/airflow/sdk/configuration.py
+++ b/task-sdk/src/airflow/sdk/configuration.py
@@ -32,7 +32,6 @@ from airflow.sdk._shared.configuration.parser import (
configure_parser_from_configuration_description,
expand_env_var,
)
-from airflow.sdk._shared.configuration.secrets_backends import Backend,
sorted_backends
from airflow.sdk._shared.module_loading import import_string
from airflow.sdk.execution_time.secrets import
_SERVER_DEFAULT_SECRETS_SEARCH_PATH
@@ -279,9 +278,6 @@ def initialize_secrets_backends(
Uses SDK's conf instead of Core's conf.
"""
- # Lazy import to trigger __getattr__ and lazy initialization
- from airflow.sdk.configuration import conf
-
backend_list = []
worker_mode = False
# Determine worker mode - if default_backends is not the server default,
it's worker mode
@@ -295,7 +291,7 @@ def initialize_secrets_backends(
from airflow.sdk.definitions.connection import Connection
custom_secret_backend._set_connection_class(Connection)
- backend_list.append((Backend.CUSTOM, custom_secret_backend))
+ backend_list.append(custom_secret_backend)
for class_name in default_backends:
from airflow.sdk.definitions.connection import Connection
@@ -303,9 +299,9 @@ def initialize_secrets_backends(
secrets_backend_cls = import_string(class_name)
backend = secrets_backend_cls()
backend._set_connection_class(Connection)
- backend_list.append((Backend.from_path(class_name), backend))
+ backend_list.append(backend)
- return sorted_backends(conf, backend_list, worker_mode)
+ return backend_list
_secrets_backend_cache: dict[tuple[str, ...], list] = {}
diff --git a/task-sdk/src/airflow/sdk/execution_time/secrets/__init__.py
b/task-sdk/src/airflow/sdk/execution_time/secrets/__init__.py
index 1df88182c57..fea23f33148 100644
--- a/task-sdk/src/airflow/sdk/execution_time/secrets/__init__.py
+++ b/task-sdk/src/airflow/sdk/execution_time/secrets/__init__.py
@@ -19,7 +19,6 @@
from __future__ import annotations
-from airflow.sdk._shared.configuration import secrets_backends
from airflow.sdk.execution_time.secrets.execution_api import
ExecutionAPISecretsBackend
__all__ = ["ExecutionAPISecretsBackend", "DEFAULT_SECRETS_SEARCH_PATH_WORKERS"]
@@ -27,11 +26,11 @@ __all__ = ["ExecutionAPISecretsBackend",
"DEFAULT_SECRETS_SEARCH_PATH_WORKERS"]
# Server-side default secrets search path (for comparison/detection only)
# This matches what airflow-core uses but is defined here to avoid importing
from core
_SERVER_DEFAULT_SECRETS_SEARCH_PATH = [
- secrets_backends.ENVIRONMENT_VARIABLE_BACKEND_PATH,
- secrets_backends.METASTORE_BACKEND_PATH,
+ "airflow.secrets.environment_variables.EnvironmentVariablesBackend",
+ "airflow.secrets.metastore.MetastoreBackend",
]
DEFAULT_SECRETS_SEARCH_PATH_WORKERS = [
- secrets_backends.ENVIRONMENT_VARIABLE_BACKEND_PATH,
- secrets_backends.EXECUTION_API_BACKEND_PATH,
+ "airflow.secrets.environment_variables.EnvironmentVariablesBackend",
+
"airflow.sdk.execution_time.secrets.execution_api.ExecutionAPISecretsBackend",
]
diff --git a/task-sdk/src/airflow/sdk/execution_time/supervisor.py
b/task-sdk/src/airflow/sdk/execution_time/supervisor.py
index d186644e4b6..312766cd756 100644
--- a/task-sdk/src/airflow/sdk/execution_time/supervisor.py
+++ b/task-sdk/src/airflow/sdk/execution_time/supervisor.py
@@ -61,7 +61,6 @@ import psutil
import structlog
from pydantic import BaseModel, TypeAdapter
-from airflow.sdk._shared.configuration import secrets_backends
from airflow.sdk._shared.logging.structlog import reconfigure_logger
from airflow.sdk.api.client import Client, ServerResponseError
from airflow.sdk.api.datamodels._generated import (
@@ -2861,7 +2860,7 @@ def ensure_secrets_backend_loaded() ->
list[BaseSecretsBackend]:
# 3. Fallback for unknown contexts (supervisor, etc.)
# Only env vars + external backends from config, no MetastoreBackend, no
ExecutionAPISecretsBackend
fallback_backends = [
- secrets_backends.ENVIRONMENT_VARIABLE_BACKEND_PATH,
+ "airflow.secrets.environment_variables.EnvironmentVariablesBackend",
]
return ensure_secrets_loaded(default_backends=fallback_backends)
diff --git a/task-sdk/tests/task_sdk/execution_time/test_context.py
b/task-sdk/tests/task_sdk/execution_time/test_context.py
index 0b2305f12c5..3c8c5924423 100644
--- a/task-sdk/tests/task_sdk/execution_time/test_context.py
+++ b/task-sdk/tests/task_sdk/execution_time/test_context.py
@@ -27,7 +27,6 @@ import pytest
from pydantic import ValidationError
from airflow.sdk import BaseOperator, get_current_context, timezone
-from airflow.sdk._shared.configuration import secrets_backends
from airflow.sdk._shared.state import AssetScope, TaskScope
from airflow.sdk.api.datamodels._generated import (
AssetEventResponse,
@@ -1320,14 +1319,20 @@ class TestSecretsBackend:
"""Test that ExecutionAPISecretsBackend is in the worker search
path."""
from airflow.sdk.execution_time.secrets import
DEFAULT_SECRETS_SEARCH_PATH_WORKERS
- assert secrets_backends.EXECUTION_API_BACKEND_PATH in
DEFAULT_SECRETS_SEARCH_PATH_WORKERS
+ assert (
+
"airflow.sdk.execution_time.secrets.execution_api.ExecutionAPISecretsBackend"
+ in DEFAULT_SECRETS_SEARCH_PATH_WORKERS
+ )
def test_metastore_backend_in_server_chain(self):
"""Test that MetastoreBackend is in the API server search path."""
from airflow.sdk.execution_time.secrets import
_SERVER_DEFAULT_SECRETS_SEARCH_PATH
- assert secrets_backends.METASTORE_BACKEND_PATH in
_SERVER_DEFAULT_SECRETS_SEARCH_PATH
- assert secrets_backends.EXECUTION_API_BACKEND_PATH not in
_SERVER_DEFAULT_SECRETS_SEARCH_PATH
+ assert "airflow.secrets.metastore.MetastoreBackend" in
_SERVER_DEFAULT_SECRETS_SEARCH_PATH
+ assert (
+
"airflow.sdk.execution_time.secrets.execution_api.ExecutionAPISecretsBackend"
+ not in _SERVER_DEFAULT_SECRETS_SEARCH_PATH
+ )
def test_get_connection_uses_backend_chain(self, mock_supervisor_comms):
"""Test that _get_connection properly iterates through backends."""
diff --git a/task-sdk/tests/task_sdk/execution_time/test_secrets.py
b/task-sdk/tests/task_sdk/execution_time/test_secrets.py
index b63e77b2407..2fe41e328ce 100644
--- a/task-sdk/tests/task_sdk/execution_time/test_secrets.py
+++ b/task-sdk/tests/task_sdk/execution_time/test_secrets.py
@@ -19,7 +19,6 @@ from __future__ import annotations
import pytest
-from airflow.sdk._shared.configuration import secrets_backends
from airflow.sdk.api.datamodels._generated import ConnectionResponse
from airflow.sdk.configuration import clear_secrets_backends_cache,
ensure_secrets_loaded
from airflow.sdk.exceptions import AirflowSecretsBackendAccessDenied, ErrorType
@@ -311,7 +310,7 @@ class TestContextDetection:
class TestSecretsBackendMemoisation:
- BACKEND = secrets_backends.ENVIRONMENT_VARIABLE_BACKEND_PATH
+ BACKEND =
"airflow.secrets.environment_variables.EnvironmentVariablesBackend"
def test_nothing_is_memoised_until_a_custom_backend_is_configured(self):
first =
ensure_secrets_loaded(default_backends=_SERVER_DEFAULT_SECRETS_SEARCH_PATH)