Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add service endpoint to provide hook meta data for UI #47588

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
48 changes: 48 additions & 0 deletions airflow/api_fastapi/core_api/datamodels/connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
from __future__ import annotations

import json
from collections import abc
from typing import Annotated

from pydantic import Field, field_validator
from pydantic_core.core_schema import ValidationInfo
Expand Down Expand Up @@ -75,6 +77,52 @@ class ConnectionTestResponse(BaseModel):
message: str


class ConnectionHookFieldBehavior(BaseModel):
"""A class to store the behavior of each standard field of a Hook."""

hidden: Annotated[
bool,
Field(description="Flag if the form field should be hidden."),
] = False
title: Annotated[
str | None,
Field(
description="Label / title for the field that should be displayed, if re-labelling is needed. Use `None` to display standard title."
),
] = None
placeholder: Annotated[
str | None,
Field(description="Placeholder text that should be populated to the form."),
] = None


class StandardHookFields(BaseModel):
"""Standard fields of a Hook that a form will render."""

description: ConnectionHookFieldBehavior | None
url_schema: ConnectionHookFieldBehavior | None
host: ConnectionHookFieldBehavior | None
port: ConnectionHookFieldBehavior | None
login: ConnectionHookFieldBehavior | None
password: ConnectionHookFieldBehavior | None


class ConnectionHookMetaData(BaseModel):
"""
Response model for Hook information == Connection type meta data.
It is used to transfer providers information loaded by providers_manager such that
the API server/Web UI can use this data to render connection form UI.
"""

connection_type: str | None
hook_class_name: str | None
default_conn_name: str | None
hook_name: str
standard_fields: StandardHookFields | None
extra_fields: abc.MutableMapping | None


# Request Models
class ConnectionBody(StrictBaseModel):
"""Connection Serializer for requests body."""
Expand Down
124 changes: 124 additions & 0 deletions airflow/api_fastapi/core_api/openapi/v1-generated.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,26 @@ paths:
$ref: '#/components/schemas/HTTPExceptionResponse'
security:
- OAuth2PasswordBearer: []
/ui/connections/hook_meta:
get:
tags:
- Connection
summary: Hook Meta Data
description: Retrieve information about available connection types (hook classes)
and their parameters.
operationId: hook_meta_data
responses:
'200':
description: Successful Response
content:
application/json:
schema:
items:
$ref: '#/components/schemas/ConnectionHookMetaData'
type: array
title: Response Hook Meta Data
security:
- OAuth2PasswordBearer: []
/ui/dags/recent_dag_runs:
get:
tags:
Expand Down Expand Up @@ -8117,6 +8137,74 @@ components:
- total_entries
title: ConnectionCollectionResponse
description: Connection Collection serializer for responses.
ConnectionHookFieldBehavior:
properties:
hidden:
type: boolean
title: Hidden
description: Flag if the form field should be hidden.
default: false
title:
anyOf:
- type: string
- type: 'null'
title: Title
description: Label / title for the field that should be displayed, if re-labelling
is needed. Use `None` to display standard title.
placeholder:
anyOf:
- type: string
- type: 'null'
title: Placeholder
description: Placeholder text that should be populated to the form.
type: object
title: ConnectionHookFieldBehavior
description: A class to store the behavior of each standard field of a Hook.
ConnectionHookMetaData:
properties:
connection_type:
anyOf:
- type: string
- type: 'null'
title: Connection Type
hook_class_name:
anyOf:
- type: string
- type: 'null'
title: Hook Class Name
default_conn_name:
anyOf:
- type: string
- type: 'null'
title: Default Conn Name
hook_name:
type: string
title: Hook Name
standard_fields:
anyOf:
- $ref: '#/components/schemas/StandardHookFields'
- type: 'null'
extra_fields:
anyOf:
- type: object
- type: 'null'
title: Extra Fields
type: object
required:
- connection_type
- hook_class_name
- default_conn_name
- hook_name
- standard_fields
- extra_fields
title: ConnectionHookMetaData
description: 'Response model for Hook information == Connection type meta data.
It is used to transfer providers information loaded by providers_manager such
that
the API server/Web UI can use this data to render connection form UI.'
ConnectionResponse:
properties:
connection_id:
Expand Down Expand Up @@ -10218,6 +10306,42 @@ components:
- latest_scheduler_heartbeat
title: SchedulerInfoResponse
description: Scheduler info serializer for responses.
StandardHookFields:
properties:
description:
anyOf:
- $ref: '#/components/schemas/ConnectionHookFieldBehavior'
- type: 'null'
url_schema:
anyOf:
- $ref: '#/components/schemas/ConnectionHookFieldBehavior'
- type: 'null'
host:
anyOf:
- $ref: '#/components/schemas/ConnectionHookFieldBehavior'
- type: 'null'
port:
anyOf:
- $ref: '#/components/schemas/ConnectionHookFieldBehavior'
- type: 'null'
login:
anyOf:
- $ref: '#/components/schemas/ConnectionHookFieldBehavior'
- type: 'null'
password:
anyOf:
- $ref: '#/components/schemas/ConnectionHookFieldBehavior'
- type: 'null'
type: object
required:
- description
- url_schema
- host
- port
- login
- password
title: StandardHookFields
description: Standard fields of a Hook that a form will render.
StructureDataResponse:
properties:
edges:
Expand Down
2 changes: 2 additions & 0 deletions airflow/api_fastapi/core_api/routes/ui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from airflow.api_fastapi.core_api.routes.ui.assets import assets_router
from airflow.api_fastapi.core_api.routes.ui.backfills import backfills_router
from airflow.api_fastapi.core_api.routes.ui.config import config_router
from airflow.api_fastapi.core_api.routes.ui.connections import connections_router
from airflow.api_fastapi.core_api.routes.ui.dags import dags_router
from airflow.api_fastapi.core_api.routes.ui.dashboard import dashboard_router
from airflow.api_fastapi.core_api.routes.ui.dependencies import dependencies_router
Expand All @@ -30,6 +31,7 @@

ui_router.include_router(assets_router)
ui_router.include_router(config_router)
ui_router.include_router(connections_router)
ui_router.include_router(dags_router)
ui_router.include_router(dependencies_router)
ui_router.include_router(dashboard_router)
Expand Down
40 changes: 40 additions & 0 deletions airflow/api_fastapi/core_api/routes/ui/connections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# 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

from fastapi import Depends

from airflow.api_fastapi.common.router import AirflowRouter
from airflow.api_fastapi.core_api.datamodels.connections import ConnectionHookMetaData
from airflow.api_fastapi.core_api.security import requires_access_connection
from airflow.api_fastapi.core_api.services.ui.connections import HookMetaService

connections_router = AirflowRouter(tags=["Connection"], prefix="/connections")


@connections_router.get(
"/hook_meta",
dependencies=[Depends(requires_access_connection(method="GET"))],
)
def hook_meta_data() -> list[ConnectionHookMetaData]:
"""Retrieve information about available connection types (hook classes) and their parameters."""
# Note:
# This endpoint is implemented to serve the connections form in the UI. It is building on providers
# manager and hooks being loaded in the API server. Target should be that the API server reads the
# information from a database table to un-bundle the dependency for provider package install from
# the API server.
return HookMetaService.hook_meta_data()
Loading
Loading