Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,37 @@ paths:
security:
- OAuth2PasswordBearer: []
- HTTPBearer: []
/ui/connections/hook_meta/{connection_type}:
get:
tags:
- Connection
summary: Hook Meta Data For Type
description: Return full metadata (standard_fields, extra_fields) for a single
connection type.
operationId: hook_meta_data_for_type
security:
- OAuth2PasswordBearer: []
- HTTPBearer: []
parameters:
- name: connection_type
in: path
required: true
schema:
type: string
title: Connection Type
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ConnectionHookMetaData'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/ui/connections/hook_meta:
get:
tags:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# under the License.
from __future__ import annotations

from fastapi import Depends
from fastapi import Depends, HTTPException

from airflow.api_fastapi.common.router import AirflowRouter
from airflow.api_fastapi.core_api.datamodels.connections import ConnectionHookMetaData
Expand All @@ -26,6 +26,18 @@
connections_router = AirflowRouter(tags=["Connection"], prefix="/connections")


@connections_router.get(
"/hook_meta/{connection_type}",
dependencies=[Depends(requires_access_connection(method="GET"))],
)
def hook_meta_data_for_type(connection_type: str) -> ConnectionHookMetaData:
"""Return full metadata (standard_fields, extra_fields) for a single connection type."""
result = HookMetaService.hook_meta_for_type(connection_type)
if result is None:
raise HTTPException(status_code=404, detail=f"Connection type '{connection_type}' not found")
return result


@connections_router.get(
"/hook_meta",
dependencies=[Depends(requires_access_connection(method="GET"))],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,80 @@ def hook_meta_data() -> list[ConnectionHookMetaData]:
)
result.append(hook_meta)
return result

@staticmethod
def hook_meta_for_type(connection_type: str) -> ConnectionHookMetaData | None:
"""
Return full metadata for a single connection type.

Only imports the requested hook class (via lazy dict lookup), not all hooks.
"""
from unittest import mock

from airflow.providers_manager import ProvidersManager

def mock_lazy_gettext(txt: str) -> str:
return txt

def mock_any_of(allowed_values: list) -> HookMetaService.MockEnum:
return HookMetaService.MockEnum(allowed_values)

import sys
from importlib.util import find_spec
from unittest.mock import MagicMock

for mod_name in [
"wtforms",
"wtforms.csrf",
"wtforms.fields",
"wtforms.fields.simple",
"wtforms.validators",
"flask_babel",
"flask_appbuilder",
"flask_appbuilder.fieldwidgets",
]:
try:
if not find_spec(mod_name):
raise ModuleNotFoundError
except ModuleNotFoundError:
sys.modules[mod_name] = MagicMock()
with (
mock.patch("wtforms.StringField", HookMetaService.MockStringField),
mock.patch("wtforms.fields.StringField", HookMetaService.MockStringField),
mock.patch("wtforms.fields.simple.StringField", HookMetaService.MockStringField),
mock.patch("wtforms.IntegerField", HookMetaService.MockIntegerField),
mock.patch("wtforms.fields.IntegerField", HookMetaService.MockIntegerField),
mock.patch("wtforms.PasswordField", HookMetaService.MockPasswordField),
mock.patch("wtforms.BooleanField", HookMetaService.MockBooleanField),
mock.patch("wtforms.fields.BooleanField", HookMetaService.MockBooleanField),
mock.patch("wtforms.fields.simple.BooleanField", HookMetaService.MockBooleanField),
mock.patch("flask_babel.lazy_gettext", mock_lazy_gettext),
mock.patch("flask_appbuilder.fieldwidgets.BS3TextFieldWidget", HookMetaService.MockAnyWidget),
mock.patch("flask_appbuilder.fieldwidgets.BS3TextAreaFieldWidget", HookMetaService.MockAnyWidget),
mock.patch("flask_appbuilder.fieldwidgets.BS3PasswordFieldWidget", HookMetaService.MockAnyWidget),
mock.patch("wtforms.validators.Optional", HookMetaService.MockOptional),
mock.patch("wtforms.validators.any_of", mock_any_of),
):
pm = ProvidersManager()
pm.initialize_providers_hooks()

if connection_type not in pm._hooks_lazy_dict:
return None
hook_info = pm._hooks_lazy_dict[connection_type]
if not hook_info:
return None

prefix = f"extra__{connection_type}__"
filtered_widgets = {k: v for k, v in pm._connection_form_widgets.items() if k.startswith(prefix)}
widgets = HookMetaService._convert_extra_fields(filtered_widgets)

return ConnectionHookMetaData(
connection_type=connection_type,
hook_class_name=hook_info.hook_class_name,
default_conn_name=None,
hook_name=hook_info.hook_name,
standard_fields=HookMetaService._make_standard_fields(
pm._field_behaviours.get(connection_type)
),
extra_fields=widgets.get(connection_type),
)
6 changes: 6 additions & 0 deletions airflow-core/src/airflow/ui/openapi-gen/queries/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ export const UseConnectionServiceGetConnectionsKeyFn = ({ connectionIdPattern, l
offset?: number;
orderBy?: string[];
} = {}, queryKey?: Array<unknown>) => [useConnectionServiceGetConnectionsKey, ...(queryKey ?? [{ connectionIdPattern, limit, offset, orderBy }])];
export type ConnectionServiceHookMetaDataForTypeDefaultResponse = Awaited<ReturnType<typeof ConnectionService.hookMetaDataForType>>;
export type ConnectionServiceHookMetaDataForTypeQueryResult<TData = ConnectionServiceHookMetaDataForTypeDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
export const useConnectionServiceHookMetaDataForTypeKey = "ConnectionServiceHookMetaDataForType";
export const UseConnectionServiceHookMetaDataForTypeKeyFn = ({ connectionType }: {
connectionType: string;
}, queryKey?: Array<unknown>) => [useConnectionServiceHookMetaDataForTypeKey, ...(queryKey ?? [{ connectionType }])];
export type ConnectionServiceHookMetaDataDefaultResponse = Awaited<ReturnType<typeof ConnectionService.hookMetaData>>;
export type ConnectionServiceHookMetaDataQueryResult<TData = ConnectionServiceHookMetaDataDefaultResponse, TError = unknown> = UseQueryResult<TData, TError>;
export const useConnectionServiceHookMetaDataKey = "ConnectionServiceHookMetaData";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,17 @@ export const ensureUseConnectionServiceGetConnectionsData = (queryClient: QueryC
orderBy?: string[];
} = {}) => queryClient.ensureQueryData({ queryKey: Common.UseConnectionServiceGetConnectionsKeyFn({ connectionIdPattern, limit, offset, orderBy }), queryFn: () => ConnectionService.getConnections({ connectionIdPattern, limit, offset, orderBy }) });
/**
* Hook Meta Data For Type
* Return full metadata (standard_fields, extra_fields) for a single connection type.
* @param data The data for the request.
* @param data.connectionType
* @returns ConnectionHookMetaData Successful Response
* @throws ApiError
*/
export const ensureUseConnectionServiceHookMetaDataForTypeData = (queryClient: QueryClient, { connectionType }: {
connectionType: string;
}) => queryClient.ensureQueryData({ queryKey: Common.UseConnectionServiceHookMetaDataForTypeKeyFn({ connectionType }), queryFn: () => ConnectionService.hookMetaDataForType({ connectionType }) });
/**
* Hook Meta Data
* Retrieve information about available connection types (hook classes) and their parameters.
* @returns ConnectionHookMetaData Successful Response
Expand Down
11 changes: 11 additions & 0 deletions airflow-core/src/airflow/ui/openapi-gen/queries/prefetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,17 @@ export const prefetchUseConnectionServiceGetConnections = (queryClient: QueryCli
orderBy?: string[];
} = {}) => queryClient.prefetchQuery({ queryKey: Common.UseConnectionServiceGetConnectionsKeyFn({ connectionIdPattern, limit, offset, orderBy }), queryFn: () => ConnectionService.getConnections({ connectionIdPattern, limit, offset, orderBy }) });
/**
* Hook Meta Data For Type
* Return full metadata (standard_fields, extra_fields) for a single connection type.
* @param data The data for the request.
* @param data.connectionType
* @returns ConnectionHookMetaData Successful Response
* @throws ApiError
*/
export const prefetchUseConnectionServiceHookMetaDataForType = (queryClient: QueryClient, { connectionType }: {
connectionType: string;
}) => queryClient.prefetchQuery({ queryKey: Common.UseConnectionServiceHookMetaDataForTypeKeyFn({ connectionType }), queryFn: () => ConnectionService.hookMetaDataForType({ connectionType }) });
/**
* Hook Meta Data
* Retrieve information about available connection types (hook classes) and their parameters.
* @returns ConnectionHookMetaData Successful Response
Expand Down
11 changes: 11 additions & 0 deletions airflow-core/src/airflow/ui/openapi-gen/queries/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,17 @@ export const useConnectionServiceGetConnections = <TData = Common.ConnectionServ
orderBy?: string[];
} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: Common.UseConnectionServiceGetConnectionsKeyFn({ connectionIdPattern, limit, offset, orderBy }, queryKey), queryFn: () => ConnectionService.getConnections({ connectionIdPattern, limit, offset, orderBy }) as TData, ...options });
/**
* Hook Meta Data For Type
* Return full metadata (standard_fields, extra_fields) for a single connection type.
* @param data The data for the request.
* @param data.connectionType
* @returns ConnectionHookMetaData Successful Response
* @throws ApiError
*/
export const useConnectionServiceHookMetaDataForType = <TData = Common.ConnectionServiceHookMetaDataForTypeDefaultResponse, TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ connectionType }: {
connectionType: string;
}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useQuery<TData, TError>({ queryKey: Common.UseConnectionServiceHookMetaDataForTypeKeyFn({ connectionType }, queryKey), queryFn: () => ConnectionService.hookMetaDataForType({ connectionType }) as TData, ...options });
/**
* Hook Meta Data
* Retrieve information about available connection types (hook classes) and their parameters.
* @returns ConnectionHookMetaData Successful Response
Expand Down
11 changes: 11 additions & 0 deletions airflow-core/src/airflow/ui/openapi-gen/queries/suspense.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,17 @@ export const useConnectionServiceGetConnectionsSuspense = <TData = Common.Connec
orderBy?: string[];
} = {}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey: Common.UseConnectionServiceGetConnectionsKeyFn({ connectionIdPattern, limit, offset, orderBy }, queryKey), queryFn: () => ConnectionService.getConnections({ connectionIdPattern, limit, offset, orderBy }) as TData, ...options });
/**
* Hook Meta Data For Type
* Return full metadata (standard_fields, extra_fields) for a single connection type.
* @param data The data for the request.
* @param data.connectionType
* @returns ConnectionHookMetaData Successful Response
* @throws ApiError
*/
export const useConnectionServiceHookMetaDataForTypeSuspense = <TData = Common.ConnectionServiceHookMetaDataForTypeDefaultResponse, TError = unknown, TQueryKey extends Array<unknown> = unknown[]>({ connectionType }: {
connectionType: string;
}, queryKey?: TQueryKey, options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">) => useSuspenseQuery<TData, TError>({ queryKey: Common.UseConnectionServiceHookMetaDataForTypeKeyFn({ connectionType }, queryKey), queryFn: () => ConnectionService.hookMetaDataForType({ connectionType }) as TData, ...options });
/**
* Hook Meta Data
* Retrieve information about available connection types (hook classes) and their parameters.
* @returns ConnectionHookMetaData Successful Response
Expand Down
Loading
Loading