Skip to content

Commit 3539190

Browse files
authored
Add service endpoint to provide hook meta data for UI (#47588)
* Add service endpoint to provide hook meta data for UI * Review Feedback * Add pytest, re-wire ui connection endpoint * Re-naming class feedback * Revert import formatting change * Make test as DB test for FAB auth
1 parent 6994f1f commit 3539190

File tree

13 files changed

+1471
-687
lines changed

13 files changed

+1471
-687
lines changed

airflow/api_fastapi/core_api/datamodels/connections.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
from __future__ import annotations
1919

2020
import json
21+
from collections import abc
22+
from typing import Annotated
2123

2224
from pydantic import Field, field_validator
2325
from pydantic_core.core_schema import ValidationInfo
@@ -75,6 +77,52 @@ class ConnectionTestResponse(BaseModel):
7577
message: str
7678

7779

80+
class ConnectionHookFieldBehavior(BaseModel):
81+
"""A class to store the behavior of each standard field of a Hook."""
82+
83+
hidden: Annotated[
84+
bool,
85+
Field(description="Flag if the form field should be hidden."),
86+
] = False
87+
title: Annotated[
88+
str | None,
89+
Field(
90+
description="Label / title for the field that should be displayed, if re-labelling is needed. Use `None` to display standard title."
91+
),
92+
] = None
93+
placeholder: Annotated[
94+
str | None,
95+
Field(description="Placeholder text that should be populated to the form."),
96+
] = None
97+
98+
99+
class StandardHookFields(BaseModel):
100+
"""Standard fields of a Hook that a form will render."""
101+
102+
description: ConnectionHookFieldBehavior | None
103+
url_schema: ConnectionHookFieldBehavior | None
104+
host: ConnectionHookFieldBehavior | None
105+
port: ConnectionHookFieldBehavior | None
106+
login: ConnectionHookFieldBehavior | None
107+
password: ConnectionHookFieldBehavior | None
108+
109+
110+
class ConnectionHookMetaData(BaseModel):
111+
"""
112+
Response model for Hook information == Connection type meta data.
113+
114+
It is used to transfer providers information loaded by providers_manager such that
115+
the API server/Web UI can use this data to render connection form UI.
116+
"""
117+
118+
connection_type: str | None
119+
hook_class_name: str | None
120+
default_conn_name: str | None
121+
hook_name: str
122+
standard_fields: StandardHookFields | None
123+
extra_fields: abc.MutableMapping | None
124+
125+
78126
# Request Models
79127
class ConnectionBody(StrictBaseModel):
80128
"""Connection Serializer for requests body."""

airflow/api_fastapi/core_api/openapi/v1-generated.yaml

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,26 @@ paths:
5858
$ref: '#/components/schemas/HTTPExceptionResponse'
5959
security:
6060
- OAuth2PasswordBearer: []
61+
/ui/connections/hook_meta:
62+
get:
63+
tags:
64+
- Connection
65+
summary: Hook Meta Data
66+
description: Retrieve information about available connection types (hook classes)
67+
and their parameters.
68+
operationId: hook_meta_data
69+
responses:
70+
'200':
71+
description: Successful Response
72+
content:
73+
application/json:
74+
schema:
75+
items:
76+
$ref: '#/components/schemas/ConnectionHookMetaData'
77+
type: array
78+
title: Response Hook Meta Data
79+
security:
80+
- OAuth2PasswordBearer: []
6181
/ui/dags/recent_dag_runs:
6282
get:
6383
tags:
@@ -8121,6 +8141,74 @@ components:
81218141
- total_entries
81228142
title: ConnectionCollectionResponse
81238143
description: Connection Collection serializer for responses.
8144+
ConnectionHookFieldBehavior:
8145+
properties:
8146+
hidden:
8147+
type: boolean
8148+
title: Hidden
8149+
description: Flag if the form field should be hidden.
8150+
default: false
8151+
title:
8152+
anyOf:
8153+
- type: string
8154+
- type: 'null'
8155+
title: Title
8156+
description: Label / title for the field that should be displayed, if re-labelling
8157+
is needed. Use `None` to display standard title.
8158+
placeholder:
8159+
anyOf:
8160+
- type: string
8161+
- type: 'null'
8162+
title: Placeholder
8163+
description: Placeholder text that should be populated to the form.
8164+
type: object
8165+
title: ConnectionHookFieldBehavior
8166+
description: A class to store the behavior of each standard field of a Hook.
8167+
ConnectionHookMetaData:
8168+
properties:
8169+
connection_type:
8170+
anyOf:
8171+
- type: string
8172+
- type: 'null'
8173+
title: Connection Type
8174+
hook_class_name:
8175+
anyOf:
8176+
- type: string
8177+
- type: 'null'
8178+
title: Hook Class Name
8179+
default_conn_name:
8180+
anyOf:
8181+
- type: string
8182+
- type: 'null'
8183+
title: Default Conn Name
8184+
hook_name:
8185+
type: string
8186+
title: Hook Name
8187+
standard_fields:
8188+
anyOf:
8189+
- $ref: '#/components/schemas/StandardHookFields'
8190+
- type: 'null'
8191+
extra_fields:
8192+
anyOf:
8193+
- type: object
8194+
- type: 'null'
8195+
title: Extra Fields
8196+
type: object
8197+
required:
8198+
- connection_type
8199+
- hook_class_name
8200+
- default_conn_name
8201+
- hook_name
8202+
- standard_fields
8203+
- extra_fields
8204+
title: ConnectionHookMetaData
8205+
description: 'Response model for Hook information == Connection type meta data.
8206+
8207+
8208+
It is used to transfer providers information loaded by providers_manager such
8209+
that
8210+
8211+
the API server/Web UI can use this data to render connection form UI.'
81248212
ConnectionResponse:
81258213
properties:
81268214
connection_id:
@@ -10228,6 +10316,42 @@ components:
1022810316
- latest_scheduler_heartbeat
1022910317
title: SchedulerInfoResponse
1023010318
description: Scheduler info serializer for responses.
10319+
StandardHookFields:
10320+
properties:
10321+
description:
10322+
anyOf:
10323+
- $ref: '#/components/schemas/ConnectionHookFieldBehavior'
10324+
- type: 'null'
10325+
url_schema:
10326+
anyOf:
10327+
- $ref: '#/components/schemas/ConnectionHookFieldBehavior'
10328+
- type: 'null'
10329+
host:
10330+
anyOf:
10331+
- $ref: '#/components/schemas/ConnectionHookFieldBehavior'
10332+
- type: 'null'
10333+
port:
10334+
anyOf:
10335+
- $ref: '#/components/schemas/ConnectionHookFieldBehavior'
10336+
- type: 'null'
10337+
login:
10338+
anyOf:
10339+
- $ref: '#/components/schemas/ConnectionHookFieldBehavior'
10340+
- type: 'null'
10341+
password:
10342+
anyOf:
10343+
- $ref: '#/components/schemas/ConnectionHookFieldBehavior'
10344+
- type: 'null'
10345+
type: object
10346+
required:
10347+
- description
10348+
- url_schema
10349+
- host
10350+
- port
10351+
- login
10352+
- password
10353+
title: StandardHookFields
10354+
description: Standard fields of a Hook that a form will render.
1023110355
StructureDataResponse:
1023210356
properties:
1023310357
edges:

airflow/api_fastapi/core_api/routes/ui/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from airflow.api_fastapi.core_api.routes.ui.assets import assets_router
2121
from airflow.api_fastapi.core_api.routes.ui.backfills import backfills_router
2222
from airflow.api_fastapi.core_api.routes.ui.config import config_router
23+
from airflow.api_fastapi.core_api.routes.ui.connections import connections_router
2324
from airflow.api_fastapi.core_api.routes.ui.dags import dags_router
2425
from airflow.api_fastapi.core_api.routes.ui.dashboard import dashboard_router
2526
from airflow.api_fastapi.core_api.routes.ui.dependencies import dependencies_router
@@ -30,6 +31,7 @@
3031

3132
ui_router.include_router(assets_router)
3233
ui_router.include_router(config_router)
34+
ui_router.include_router(connections_router)
3335
ui_router.include_router(dags_router)
3436
ui_router.include_router(dependencies_router)
3537
ui_router.include_router(dashboard_router)
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
from __future__ import annotations
18+
19+
from fastapi import Depends
20+
21+
from airflow.api_fastapi.common.router import AirflowRouter
22+
from airflow.api_fastapi.core_api.datamodels.connections import ConnectionHookMetaData
23+
from airflow.api_fastapi.core_api.security import requires_access_connection
24+
from airflow.api_fastapi.core_api.services.ui.connections import HookMetaService
25+
26+
connections_router = AirflowRouter(tags=["Connection"], prefix="/connections")
27+
28+
29+
@connections_router.get(
30+
"/hook_meta",
31+
dependencies=[Depends(requires_access_connection(method="GET"))],
32+
)
33+
def hook_meta_data() -> list[ConnectionHookMetaData]:
34+
"""Retrieve information about available connection types (hook classes) and their parameters."""
35+
# Note:
36+
# This endpoint is implemented to serve the connections form in the UI. It is building on providers
37+
# manager and hooks being loaded in the API server. Target should be that the API server reads the
38+
# information from a database table to un-bundle the dependency for provider package install from
39+
# the API server.
40+
return HookMetaService.hook_meta_data()

0 commit comments

Comments
 (0)