This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun 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 69cd23722d7 AIP-84 Migrate private graph_data endpoint (#44394)
69cd23722d7 is described below
commit 69cd23722d79bf19ee36f9ff57c6a822e87ba1f1
Author: Pierre Jeambrun <[email protected]>
AuthorDate: Thu Nov 28 23:11:13 2024 +0800
AIP-84 Migrate private graph_data endpoint (#44394)
* Working basic version
* Add tests
---
.../api_fastapi/core_api/datamodels/ui/graph.py | 60 +++++
.../api_fastapi/core_api/openapi/v1-generated.yaml | 251 ++++++++++++++++++---
airflow/api_fastapi/core_api/routes/ui/__init__.py | 6 +-
.../api_fastapi/core_api/routes/ui/dashboard.py | 4 +-
airflow/api_fastapi/core_api/routes/ui/graph.py | 66 ++++++
airflow/ui/openapi-gen/queries/common.ts | 128 ++++++-----
airflow/ui/openapi-gen/queries/prefetch.ts | 149 +++++++-----
airflow/ui/openapi-gen/queries/queries.ts | 171 ++++++++------
airflow/ui/openapi-gen/queries/suspense.ts | 171 ++++++++------
airflow/ui/openapi-gen/requests/schemas.gen.ts | 195 ++++++++++++++++
airflow/ui/openapi-gen/requests/services.gen.ts | 172 ++++++++------
airflow/ui/openapi-gen/requests/types.gen.ts | 171 ++++++++++----
tests/api_fastapi/core_api/routes/ui/test_graph.py | 198 ++++++++++++++++
13 files changed, 1352 insertions(+), 390 deletions(-)
diff --git a/airflow/api_fastapi/core_api/datamodels/ui/graph.py
b/airflow/api_fastapi/core_api/datamodels/ui/graph.py
new file mode 100644
index 00000000000..b4d7587b35e
--- /dev/null
+++ b/airflow/api_fastapi/core_api/datamodels/ui/graph.py
@@ -0,0 +1,60 @@
+# 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 typing import Literal
+
+from airflow.api_fastapi.core_api.base import BaseModel
+
+
+class EdgeResponse(BaseModel):
+ """Edge serializer for responses."""
+
+ is_setup_teardown: bool | None = None
+ label: str | None = None
+ source_id: str
+ target_id: str
+
+
+class NodeValueResponse(BaseModel):
+ """Graph Node Value responses."""
+
+ isMapped: bool | None = None
+ label: str | None = None
+ labelStyle: str | None = None
+ style: str | None = None
+ tooltip: str | None = None
+ rx: int
+ ry: int
+ clusterLabelPos: str | None = None
+ setupTeardownType: Literal["setup", "teardown"] | None = None
+
+
+class NodeResponse(BaseModel):
+ """Node serializer for responses."""
+
+ children: list[NodeResponse] | None = None
+ id: str | None
+ value: NodeValueResponse
+
+
+class GraphDataResponse(BaseModel):
+ """Graph Data serializer for responses."""
+
+ edges: list[EdgeResponse]
+ nodes: NodeResponse
+ arrange: Literal["BT", "LR", "RL", "TB"]
diff --git a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
index 25ade1d9171..700f65a1b9d 100644
--- a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
+++ b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml
@@ -34,47 +34,26 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
- /ui/dashboard/historical_metrics_data:
+ /ui/config:
get:
tags:
- - Dashboard
- summary: Historical Metrics
- description: Return cluster activity historical metrics.
- operationId: historical_metrics
- parameters:
- - name: start_date
- in: query
- required: true
- schema:
- type: string
- title: Start Date
- - name: end_date
- in: query
- required: false
- schema:
- anyOf:
- - type: string
- - type: 'null'
- title: End Date
+ - Config
+ summary: Get Configs
+ description: Get configs for UI.
+ operationId: get_configs
responses:
'200':
description: Successful Response
content:
application/json:
schema:
- $ref: '#/components/schemas/HistoricalMetricDataResponse'
- '400':
+ $ref: '#/components/schemas/ConfigResponse'
+ '404':
+ description: Not Found
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPExceptionResponse'
- description: Bad Request
- '422':
- description: Validation Error
- content:
- application/json:
- schema:
- $ref: '#/components/schemas/HTTPValidationError'
/ui/dags/recent_dag_runs:
get:
tags:
@@ -174,26 +153,102 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
- /ui/config:
+ /ui/dashboard/historical_metrics_data:
get:
tags:
- - Config
- summary: Get Configs
- description: Get configs for UI.
- operationId: get_configs
+ - Dashboard
+ summary: Historical Metrics
+ description: Return cluster activity historical metrics.
+ operationId: historical_metrics
+ parameters:
+ - name: start_date
+ in: query
+ required: true
+ schema:
+ type: string
+ title: Start Date
+ - name: end_date
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: End Date
responses:
'200':
description: Successful Response
content:
application/json:
schema:
- $ref: '#/components/schemas/ConfigResponse'
- '404':
- description: Not Found
+ $ref: '#/components/schemas/HistoricalMetricDataResponse'
+ '400':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPExceptionResponse'
+ description: Bad Request
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPValidationError'
+ /ui/graph/graph_data:
+ get:
+ tags:
+ - Graph
+ summary: Graph Data
+ description: Get Graph Data.
+ operationId: graph_data
+ parameters:
+ - name: dag_id
+ in: query
+ required: true
+ schema:
+ type: string
+ title: Dag Id
+ - name: root
+ in: query
+ required: false
+ schema:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Root
+ - name: include_upstream
+ in: query
+ required: false
+ schema:
+ type: boolean
+ default: false
+ title: Include Upstream
+ - name: include_downstream
+ in: query
+ required: false
+ schema:
+ type: boolean
+ default: false
+ title: Include Downstream
+ responses:
+ '200':
+ description: Successful Response
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/GraphDataResponse'
+ '400':
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPExceptionResponse'
+ description: Bad Request
+ '422':
+ description: Validation Error
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/HTTPValidationError'
/public/assets:
get:
tags:
@@ -7296,6 +7351,30 @@ components:
This is the set of allowable values for the ``warning_type`` field
in the DagWarning model.'
+ EdgeResponse:
+ properties:
+ is_setup_teardown:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Is Setup Teardown
+ label:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Label
+ source_id:
+ type: string
+ title: Source Id
+ target_id:
+ type: string
+ title: Target Id
+ type: object
+ required:
+ - source_id
+ - target_id
+ title: EdgeResponse
+ description: Edge serializer for responses.
EventLogCollectionResponse:
properties:
event_logs:
@@ -7407,6 +7486,30 @@ components:
- name
title: FastAPIAppResponse
description: Serializer for Plugin FastAPI App responses.
+ GraphDataResponse:
+ properties:
+ edges:
+ items:
+ $ref: '#/components/schemas/EdgeResponse'
+ type: array
+ title: Edges
+ nodes:
+ $ref: '#/components/schemas/NodeResponse'
+ arrange:
+ type: string
+ enum:
+ - BT
+ - LR
+ - RL
+ - TB
+ title: Arrange
+ type: object
+ required:
+ - edges
+ - nodes
+ - arrange
+ title: GraphDataResponse
+ description: Graph Data serializer for responses.
HTTPExceptionResponse:
properties:
detail:
@@ -7584,6 +7687,80 @@ components:
- unixname
title: JobResponse
description: Job serializer for responses.
+ NodeResponse:
+ properties:
+ children:
+ anyOf:
+ - items:
+ $ref: '#/components/schemas/NodeResponse'
+ type: array
+ - type: 'null'
+ title: Children
+ id:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Id
+ value:
+ $ref: '#/components/schemas/NodeValueResponse'
+ type: object
+ required:
+ - id
+ - value
+ title: NodeResponse
+ description: Node serializer for responses.
+ NodeValueResponse:
+ properties:
+ isMapped:
+ anyOf:
+ - type: boolean
+ - type: 'null'
+ title: Ismapped
+ label:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Label
+ labelStyle:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Labelstyle
+ style:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Style
+ tooltip:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Tooltip
+ rx:
+ type: integer
+ title: Rx
+ ry:
+ type: integer
+ title: Ry
+ clusterLabelPos:
+ anyOf:
+ - type: string
+ - type: 'null'
+ title: Clusterlabelpos
+ setupTeardownType:
+ anyOf:
+ - type: string
+ enum:
+ - setup
+ - teardown
+ - type: 'null'
+ title: Setupteardowntype
+ type: object
+ required:
+ - rx
+ - ry
+ title: NodeValueResponse
+ description: Graph Node Value responses.
PatchTaskInstanceBody:
properties:
dry_run:
diff --git a/airflow/api_fastapi/core_api/routes/ui/__init__.py
b/airflow/api_fastapi/core_api/routes/ui/__init__.py
index 156c1219996..0fa150b4653 100644
--- a/airflow/api_fastapi/core_api/routes/ui/__init__.py
+++ b/airflow/api_fastapi/core_api/routes/ui/__init__.py
@@ -21,10 +21,12 @@ from airflow.api_fastapi.core_api.routes.ui.assets import
assets_router
from airflow.api_fastapi.core_api.routes.ui.config import config_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.graph import graph_data_router
ui_router = AirflowRouter(prefix="/ui")
ui_router.include_router(assets_router)
-ui_router.include_router(dashboard_router)
-ui_router.include_router(dags_router)
ui_router.include_router(config_router)
+ui_router.include_router(dags_router)
+ui_router.include_router(dashboard_router)
+ui_router.include_router(graph_data_router)
diff --git a/airflow/api_fastapi/core_api/routes/ui/dashboard.py
b/airflow/api_fastapi/core_api/routes/ui/dashboard.py
index 24682fa0c17..32d86a5caea 100644
--- a/airflow/api_fastapi/core_api/routes/ui/dashboard.py
+++ b/airflow/api_fastapi/core_api/routes/ui/dashboard.py
@@ -35,11 +35,11 @@ from airflow.api_fastapi.common.db.common import get_session
from airflow.api_fastapi.common.router import AirflowRouter
from airflow.utils import timezone
-dashboard_router = AirflowRouter(tags=["Dashboard"])
+dashboard_router = AirflowRouter(tags=["Dashboard"], prefix="/dashboard")
@dashboard_router.get(
- "/dashboard/historical_metrics_data",
+ "/historical_metrics_data",
include_in_schema=False,
responses=create_openapi_http_exception_doc([status.HTTP_400_BAD_REQUEST]),
)
diff --git a/airflow/api_fastapi/core_api/routes/ui/graph.py
b/airflow/api_fastapi/core_api/routes/ui/graph.py
new file mode 100644
index 00000000000..338f5904b89
--- /dev/null
+++ b/airflow/api_fastapi/core_api/routes/ui/graph.py
@@ -0,0 +1,66 @@
+# 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 typing import TYPE_CHECKING, Annotated
+
+from fastapi import Depends, Request, status
+from sqlalchemy.orm import Session
+
+from airflow.api_fastapi.core_api.datamodels.ui.graph import GraphDataResponse
+from airflow.api_fastapi.core_api.openapi.exceptions import
create_openapi_http_exception_doc
+from airflow.utils.dag_edges import dag_edges
+from airflow.utils.task_group import task_group_to_dict
+
+if TYPE_CHECKING:
+ from sqlalchemy.orm import Session
+from airflow.api_fastapi.common.db.common import get_session
+from airflow.api_fastapi.common.router import AirflowRouter
+
+graph_data_router = AirflowRouter(tags=["Graph"], prefix="/graph")
+
+
+@graph_data_router.get(
+ "/graph_data",
+ include_in_schema=False,
+ responses=create_openapi_http_exception_doc([status.HTTP_400_BAD_REQUEST]),
+)
+def graph_data(
+ session: Annotated[Session, Depends(get_session)],
+ dag_id: str,
+ request: Request,
+ root: str | None = None,
+ include_upstream: bool = False,
+ include_downstream: bool = False,
+) -> GraphDataResponse:
+ """Get Graph Data."""
+ dag = request.app.state.dag_bag.get_dag(dag_id)
+ if root:
+ dag = dag.partial_subset(
+ task_ids_or_regex=root, include_upstream=include_upstream,
include_downstream=include_downstream
+ )
+
+ nodes = task_group_to_dict(dag.task_group)
+ edges = dag_edges(dag)
+
+ data = {
+ "arrange": dag.orientation,
+ "nodes": nodes,
+ "edges": edges,
+ }
+
+ return GraphDataResponse(**data)
diff --git a/airflow/ui/openapi-gen/queries/common.ts
b/airflow/ui/openapi-gen/queries/common.ts
index cb7f5c7a537..664b7a7202c 100644
--- a/airflow/ui/openapi-gen/queries/common.ts
+++ b/airflow/ui/openapi-gen/queries/common.ts
@@ -15,6 +15,7 @@ import {
DashboardService,
EventLogService,
ExtraLinksService,
+ GraphService,
ImportErrorService,
JobService,
MonitorService,
@@ -200,27 +201,58 @@ export const UseAssetServiceGetDagAssetQueuedEventKeyFn =
(
useAssetServiceGetDagAssetQueuedEventKey,
...(queryKey ?? [{ before, dagId, uri }]),
];
-export type DashboardServiceHistoricalMetricsDefaultResponse = Awaited<
- ReturnType<typeof DashboardService.historicalMetrics>
+export type ConfigServiceGetConfigsDefaultResponse = Awaited<
+ ReturnType<typeof ConfigService.getConfigs>
>;
-export type DashboardServiceHistoricalMetricsQueryResult<
- TData = DashboardServiceHistoricalMetricsDefaultResponse,
+export type ConfigServiceGetConfigsQueryResult<
+ TData = ConfigServiceGetConfigsDefaultResponse,
TError = unknown,
> = UseQueryResult<TData, TError>;
-export const useDashboardServiceHistoricalMetricsKey =
- "DashboardServiceHistoricalMetrics";
-export const UseDashboardServiceHistoricalMetricsKeyFn = (
+export const useConfigServiceGetConfigsKey = "ConfigServiceGetConfigs";
+export const UseConfigServiceGetConfigsKeyFn = (queryKey?: Array<unknown>) => [
+ useConfigServiceGetConfigsKey,
+ ...(queryKey ?? []),
+];
+export type ConfigServiceGetConfigDefaultResponse = Awaited<
+ ReturnType<typeof ConfigService.getConfig>
+>;
+export type ConfigServiceGetConfigQueryResult<
+ TData = ConfigServiceGetConfigDefaultResponse,
+ TError = unknown,
+> = UseQueryResult<TData, TError>;
+export const useConfigServiceGetConfigKey = "ConfigServiceGetConfig";
+export const UseConfigServiceGetConfigKeyFn = (
{
- endDate,
- startDate,
+ accept,
+ section,
}: {
- endDate?: string;
- startDate: string;
+ accept?: "application/json" | "text/plain" | "*/*";
+ section?: string;
+ } = {},
+ queryKey?: Array<unknown>,
+) => [useConfigServiceGetConfigKey, ...(queryKey ?? [{ accept, section }])];
+export type ConfigServiceGetConfigValueDefaultResponse = Awaited<
+ ReturnType<typeof ConfigService.getConfigValue>
+>;
+export type ConfigServiceGetConfigValueQueryResult<
+ TData = ConfigServiceGetConfigValueDefaultResponse,
+ TError = unknown,
+> = UseQueryResult<TData, TError>;
+export const useConfigServiceGetConfigValueKey = "ConfigServiceGetConfigValue";
+export const UseConfigServiceGetConfigValueKeyFn = (
+ {
+ accept,
+ option,
+ section,
+ }: {
+ accept?: "application/json" | "text/plain" | "*/*";
+ option: string;
+ section: string;
},
queryKey?: Array<unknown>,
) => [
- useDashboardServiceHistoricalMetricsKey,
- ...(queryKey ?? [{ endDate, startDate }]),
+ useConfigServiceGetConfigValueKey,
+ ...(queryKey ?? [{ accept, option, section }]),
];
export type DagsServiceRecentDagRunsDefaultResponse = Awaited<
ReturnType<typeof DagsService.recentDagRuns>
@@ -272,58 +304,52 @@ export const UseDagsServiceRecentDagRunsKeyFn = (
},
]),
];
-export type ConfigServiceGetConfigsDefaultResponse = Awaited<
- ReturnType<typeof ConfigService.getConfigs>
->;
-export type ConfigServiceGetConfigsQueryResult<
- TData = ConfigServiceGetConfigsDefaultResponse,
- TError = unknown,
-> = UseQueryResult<TData, TError>;
-export const useConfigServiceGetConfigsKey = "ConfigServiceGetConfigs";
-export const UseConfigServiceGetConfigsKeyFn = (queryKey?: Array<unknown>) => [
- useConfigServiceGetConfigsKey,
- ...(queryKey ?? []),
-];
-export type ConfigServiceGetConfigDefaultResponse = Awaited<
- ReturnType<typeof ConfigService.getConfig>
+export type DashboardServiceHistoricalMetricsDefaultResponse = Awaited<
+ ReturnType<typeof DashboardService.historicalMetrics>
>;
-export type ConfigServiceGetConfigQueryResult<
- TData = ConfigServiceGetConfigDefaultResponse,
+export type DashboardServiceHistoricalMetricsQueryResult<
+ TData = DashboardServiceHistoricalMetricsDefaultResponse,
TError = unknown,
> = UseQueryResult<TData, TError>;
-export const useConfigServiceGetConfigKey = "ConfigServiceGetConfig";
-export const UseConfigServiceGetConfigKeyFn = (
+export const useDashboardServiceHistoricalMetricsKey =
+ "DashboardServiceHistoricalMetrics";
+export const UseDashboardServiceHistoricalMetricsKeyFn = (
{
- accept,
- section,
+ endDate,
+ startDate,
}: {
- accept?: "application/json" | "text/plain" | "*/*";
- section?: string;
- } = {},
+ endDate?: string;
+ startDate: string;
+ },
queryKey?: Array<unknown>,
-) => [useConfigServiceGetConfigKey, ...(queryKey ?? [{ accept, section }])];
-export type ConfigServiceGetConfigValueDefaultResponse = Awaited<
- ReturnType<typeof ConfigService.getConfigValue>
+) => [
+ useDashboardServiceHistoricalMetricsKey,
+ ...(queryKey ?? [{ endDate, startDate }]),
+];
+export type GraphServiceGraphDataDefaultResponse = Awaited<
+ ReturnType<typeof GraphService.graphData>
>;
-export type ConfigServiceGetConfigValueQueryResult<
- TData = ConfigServiceGetConfigValueDefaultResponse,
+export type GraphServiceGraphDataQueryResult<
+ TData = GraphServiceGraphDataDefaultResponse,
TError = unknown,
> = UseQueryResult<TData, TError>;
-export const useConfigServiceGetConfigValueKey = "ConfigServiceGetConfigValue";
-export const UseConfigServiceGetConfigValueKeyFn = (
+export const useGraphServiceGraphDataKey = "GraphServiceGraphData";
+export const UseGraphServiceGraphDataKeyFn = (
{
- accept,
- option,
- section,
+ dagId,
+ includeDownstream,
+ includeUpstream,
+ root,
}: {
- accept?: "application/json" | "text/plain" | "*/*";
- option: string;
- section: string;
+ dagId: string;
+ includeDownstream?: boolean;
+ includeUpstream?: boolean;
+ root?: string;
},
queryKey?: Array<unknown>,
) => [
- useConfigServiceGetConfigValueKey,
- ...(queryKey ?? [{ accept, option, section }]),
+ useGraphServiceGraphDataKey,
+ ...(queryKey ?? [{ dagId, includeDownstream, includeUpstream, root }]),
];
export type BackfillServiceListBackfillsDefaultResponse = Awaited<
ReturnType<typeof BackfillService.listBackfills>
diff --git a/airflow/ui/openapi-gen/queries/prefetch.ts
b/airflow/ui/openapi-gen/queries/prefetch.ts
index 8f423b4c083..6dcb19267f8 100644
--- a/airflow/ui/openapi-gen/queries/prefetch.ts
+++ b/airflow/ui/openapi-gen/queries/prefetch.ts
@@ -15,6 +15,7 @@ import {
DashboardService,
EventLogService,
ExtraLinksService,
+ GraphService,
ImportErrorService,
JobService,
MonitorService,
@@ -248,30 +249,66 @@ export const
prefetchUseAssetServiceGetDagAssetQueuedEvent = (
queryFn: () => AssetService.getDagAssetQueuedEvent({ before, dagId, uri }),
});
/**
- * Historical Metrics
- * Return cluster activity historical metrics.
+ * Get Configs
+ * Get configs for UI.
+ * @returns ConfigResponse Successful Response
+ * @throws ApiError
+ */
+export const prefetchUseConfigServiceGetConfigs = (queryClient: QueryClient) =>
+ queryClient.prefetchQuery({
+ queryKey: Common.UseConfigServiceGetConfigsKeyFn(),
+ queryFn: () => ConfigService.getConfigs(),
+ });
+/**
+ * Get Config
* @param data The data for the request.
- * @param data.startDate
- * @param data.endDate
- * @returns HistoricalMetricDataResponse Successful Response
+ * @param data.section
+ * @param data.accept
+ * @returns Config Successful Response
* @throws ApiError
*/
-export const prefetchUseDashboardServiceHistoricalMetrics = (
+export const prefetchUseConfigServiceGetConfig = (
queryClient: QueryClient,
{
- endDate,
- startDate,
+ accept,
+ section,
}: {
- endDate?: string;
- startDate: string;
+ accept?: "application/json" | "text/plain" | "*/*";
+ section?: string;
+ } = {},
+) =>
+ queryClient.prefetchQuery({
+ queryKey: Common.UseConfigServiceGetConfigKeyFn({ accept, section }),
+ queryFn: () => ConfigService.getConfig({ accept, section }),
+ });
+/**
+ * Get Config Value
+ * @param data The data for the request.
+ * @param data.section
+ * @param data.option
+ * @param data.accept
+ * @returns Config Successful Response
+ * @throws ApiError
+ */
+export const prefetchUseConfigServiceGetConfigValue = (
+ queryClient: QueryClient,
+ {
+ accept,
+ option,
+ section,
+ }: {
+ accept?: "application/json" | "text/plain" | "*/*";
+ option: string;
+ section: string;
},
) =>
queryClient.prefetchQuery({
- queryKey: Common.UseDashboardServiceHistoricalMetricsKeyFn({
- endDate,
- startDate,
+ queryKey: Common.UseConfigServiceGetConfigValueKeyFn({
+ accept,
+ option,
+ section,
}),
- queryFn: () => DashboardService.historicalMetrics({ endDate, startDate }),
+ queryFn: () => ConfigService.getConfigValue({ accept, option, section }),
});
/**
* Recent Dag Runs
@@ -344,66 +381,70 @@ export const prefetchUseDagsServiceRecentDagRuns = (
}),
});
/**
- * Get Configs
- * Get configs for UI.
- * @returns ConfigResponse Successful Response
- * @throws ApiError
- */
-export const prefetchUseConfigServiceGetConfigs = (queryClient: QueryClient) =>
- queryClient.prefetchQuery({
- queryKey: Common.UseConfigServiceGetConfigsKeyFn(),
- queryFn: () => ConfigService.getConfigs(),
- });
-/**
- * Get Config
+ * Historical Metrics
+ * Return cluster activity historical metrics.
* @param data The data for the request.
- * @param data.section
- * @param data.accept
- * @returns Config Successful Response
+ * @param data.startDate
+ * @param data.endDate
+ * @returns HistoricalMetricDataResponse Successful Response
* @throws ApiError
*/
-export const prefetchUseConfigServiceGetConfig = (
+export const prefetchUseDashboardServiceHistoricalMetrics = (
queryClient: QueryClient,
{
- accept,
- section,
+ endDate,
+ startDate,
}: {
- accept?: "application/json" | "text/plain" | "*/*";
- section?: string;
- } = {},
+ endDate?: string;
+ startDate: string;
+ },
) =>
queryClient.prefetchQuery({
- queryKey: Common.UseConfigServiceGetConfigKeyFn({ accept, section }),
- queryFn: () => ConfigService.getConfig({ accept, section }),
+ queryKey: Common.UseDashboardServiceHistoricalMetricsKeyFn({
+ endDate,
+ startDate,
+ }),
+ queryFn: () => DashboardService.historicalMetrics({ endDate, startDate }),
});
/**
- * Get Config Value
+ * Graph Data
+ * Get Graph Data.
* @param data The data for the request.
- * @param data.section
- * @param data.option
- * @param data.accept
- * @returns Config Successful Response
+ * @param data.dagId
+ * @param data.root
+ * @param data.includeUpstream
+ * @param data.includeDownstream
+ * @returns GraphDataResponse Successful Response
* @throws ApiError
*/
-export const prefetchUseConfigServiceGetConfigValue = (
+export const prefetchUseGraphServiceGraphData = (
queryClient: QueryClient,
{
- accept,
- option,
- section,
+ dagId,
+ includeDownstream,
+ includeUpstream,
+ root,
}: {
- accept?: "application/json" | "text/plain" | "*/*";
- option: string;
- section: string;
+ dagId: string;
+ includeDownstream?: boolean;
+ includeUpstream?: boolean;
+ root?: string;
},
) =>
queryClient.prefetchQuery({
- queryKey: Common.UseConfigServiceGetConfigValueKeyFn({
- accept,
- option,
- section,
+ queryKey: Common.UseGraphServiceGraphDataKeyFn({
+ dagId,
+ includeDownstream,
+ includeUpstream,
+ root,
}),
- queryFn: () => ConfigService.getConfigValue({ accept, option, section }),
+ queryFn: () =>
+ GraphService.graphData({
+ dagId,
+ includeDownstream,
+ includeUpstream,
+ root,
+ }),
});
/**
* List Backfills
diff --git a/airflow/ui/openapi-gen/queries/queries.ts
b/airflow/ui/openapi-gen/queries/queries.ts
index d644beb7294..024af72e8e8 100644
--- a/airflow/ui/openapi-gen/queries/queries.ts
+++ b/airflow/ui/openapi-gen/queries/queries.ts
@@ -20,6 +20,7 @@ import {
DashboardService,
EventLogService,
ExtraLinksService,
+ GraphService,
ImportErrorService,
JobService,
MonitorService,
@@ -323,36 +324,88 @@ export const useAssetServiceGetDagAssetQueuedEvent = <
...options,
});
/**
- * Historical Metrics
- * Return cluster activity historical metrics.
+ * Get Configs
+ * Get configs for UI.
+ * @returns ConfigResponse Successful Response
+ * @throws ApiError
+ */
+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 Config
* @param data The data for the request.
- * @param data.startDate
- * @param data.endDate
- * @returns HistoricalMetricDataResponse Successful Response
+ * @param data.section
+ * @param data.accept
+ * @returns Config Successful Response
* @throws ApiError
*/
-export const useDashboardServiceHistoricalMetrics = <
- TData = Common.DashboardServiceHistoricalMetricsDefaultResponse,
+export const useConfigServiceGetConfig = <
+ TData = Common.ConfigServiceGetConfigDefaultResponse,
TError = unknown,
TQueryKey extends Array<unknown> = unknown[],
>(
{
- endDate,
- startDate,
+ accept,
+ section,
}: {
- endDate?: string;
- startDate: string;
+ accept?: "application/json" | "text/plain" | "*/*";
+ section?: string;
+ } = {},
+ queryKey?: TQueryKey,
+ options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
+) =>
+ useQuery<TData, TError>({
+ queryKey: Common.UseConfigServiceGetConfigKeyFn(
+ { accept, section },
+ queryKey,
+ ),
+ queryFn: () => ConfigService.getConfig({ accept, section }) as TData,
+ ...options,
+ });
+/**
+ * Get Config Value
+ * @param data The data for the request.
+ * @param data.section
+ * @param data.option
+ * @param data.accept
+ * @returns Config Successful Response
+ * @throws ApiError
+ */
+export const useConfigServiceGetConfigValue = <
+ TData = Common.ConfigServiceGetConfigValueDefaultResponse,
+ TError = unknown,
+ TQueryKey extends Array<unknown> = unknown[],
+>(
+ {
+ accept,
+ option,
+ section,
+ }: {
+ accept?: "application/json" | "text/plain" | "*/*";
+ option: string;
+ section: string;
},
queryKey?: TQueryKey,
options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
) =>
useQuery<TData, TError>({
- queryKey: Common.UseDashboardServiceHistoricalMetricsKeyFn(
- { endDate, startDate },
+ queryKey: Common.UseConfigServiceGetConfigValueKeyFn(
+ { accept, option, section },
queryKey,
),
queryFn: () =>
- DashboardService.historicalMetrics({ endDate, startDate }) as TData,
+ ConfigService.getConfigValue({ accept, option, section }) as TData,
...options,
});
/**
@@ -435,88 +488,80 @@ export const useDagsServiceRecentDagRuns = <
...options,
});
/**
- * Get Configs
- * Get configs for UI.
- * @returns ConfigResponse Successful Response
- * @throws ApiError
- */
-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 Config
+ * Historical Metrics
+ * Return cluster activity historical metrics.
* @param data The data for the request.
- * @param data.section
- * @param data.accept
- * @returns Config Successful Response
+ * @param data.startDate
+ * @param data.endDate
+ * @returns HistoricalMetricDataResponse Successful Response
* @throws ApiError
*/
-export const useConfigServiceGetConfig = <
- TData = Common.ConfigServiceGetConfigDefaultResponse,
+export const useDashboardServiceHistoricalMetrics = <
+ TData = Common.DashboardServiceHistoricalMetricsDefaultResponse,
TError = unknown,
TQueryKey extends Array<unknown> = unknown[],
>(
{
- accept,
- section,
+ endDate,
+ startDate,
}: {
- accept?: "application/json" | "text/plain" | "*/*";
- section?: string;
- } = {},
+ endDate?: string;
+ startDate: string;
+ },
queryKey?: TQueryKey,
options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
) =>
useQuery<TData, TError>({
- queryKey: Common.UseConfigServiceGetConfigKeyFn(
- { accept, section },
+ queryKey: Common.UseDashboardServiceHistoricalMetricsKeyFn(
+ { endDate, startDate },
queryKey,
),
- queryFn: () => ConfigService.getConfig({ accept, section }) as TData,
+ queryFn: () =>
+ DashboardService.historicalMetrics({ endDate, startDate }) as TData,
...options,
});
/**
- * Get Config Value
+ * Graph Data
+ * Get Graph Data.
* @param data The data for the request.
- * @param data.section
- * @param data.option
- * @param data.accept
- * @returns Config Successful Response
+ * @param data.dagId
+ * @param data.root
+ * @param data.includeUpstream
+ * @param data.includeDownstream
+ * @returns GraphDataResponse Successful Response
* @throws ApiError
*/
-export const useConfigServiceGetConfigValue = <
- TData = Common.ConfigServiceGetConfigValueDefaultResponse,
+export const useGraphServiceGraphData = <
+ TData = Common.GraphServiceGraphDataDefaultResponse,
TError = unknown,
TQueryKey extends Array<unknown> = unknown[],
>(
{
- accept,
- option,
- section,
+ dagId,
+ includeDownstream,
+ includeUpstream,
+ root,
}: {
- accept?: "application/json" | "text/plain" | "*/*";
- option: string;
- section: string;
+ dagId: string;
+ includeDownstream?: boolean;
+ includeUpstream?: boolean;
+ root?: string;
},
queryKey?: TQueryKey,
options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
) =>
useQuery<TData, TError>({
- queryKey: Common.UseConfigServiceGetConfigValueKeyFn(
- { accept, option, section },
+ queryKey: Common.UseGraphServiceGraphDataKeyFn(
+ { dagId, includeDownstream, includeUpstream, root },
queryKey,
),
queryFn: () =>
- ConfigService.getConfigValue({ accept, option, section }) as TData,
+ GraphService.graphData({
+ dagId,
+ includeDownstream,
+ includeUpstream,
+ root,
+ }) as TData,
...options,
});
/**
diff --git a/airflow/ui/openapi-gen/queries/suspense.ts
b/airflow/ui/openapi-gen/queries/suspense.ts
index 11386ab5d1f..0c109a46ea2 100644
--- a/airflow/ui/openapi-gen/queries/suspense.ts
+++ b/airflow/ui/openapi-gen/queries/suspense.ts
@@ -15,6 +15,7 @@ import {
DashboardService,
EventLogService,
ExtraLinksService,
+ GraphService,
ImportErrorService,
JobService,
MonitorService,
@@ -300,36 +301,88 @@ export const
useAssetServiceGetDagAssetQueuedEventSuspense = <
...options,
});
/**
- * Historical Metrics
- * Return cluster activity historical metrics.
+ * Get Configs
+ * Get configs for UI.
+ * @returns ConfigResponse Successful Response
+ * @throws ApiError
+ */
+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 Config
* @param data The data for the request.
- * @param data.startDate
- * @param data.endDate
- * @returns HistoricalMetricDataResponse Successful Response
+ * @param data.section
+ * @param data.accept
+ * @returns Config Successful Response
* @throws ApiError
*/
-export const useDashboardServiceHistoricalMetricsSuspense = <
- TData = Common.DashboardServiceHistoricalMetricsDefaultResponse,
+export const useConfigServiceGetConfigSuspense = <
+ TData = Common.ConfigServiceGetConfigDefaultResponse,
TError = unknown,
TQueryKey extends Array<unknown> = unknown[],
>(
{
- endDate,
- startDate,
+ accept,
+ section,
}: {
- endDate?: string;
- startDate: string;
+ accept?: "application/json" | "text/plain" | "*/*";
+ section?: string;
+ } = {},
+ queryKey?: TQueryKey,
+ options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
+) =>
+ useSuspenseQuery<TData, TError>({
+ queryKey: Common.UseConfigServiceGetConfigKeyFn(
+ { accept, section },
+ queryKey,
+ ),
+ queryFn: () => ConfigService.getConfig({ accept, section }) as TData,
+ ...options,
+ });
+/**
+ * Get Config Value
+ * @param data The data for the request.
+ * @param data.section
+ * @param data.option
+ * @param data.accept
+ * @returns Config Successful Response
+ * @throws ApiError
+ */
+export const useConfigServiceGetConfigValueSuspense = <
+ TData = Common.ConfigServiceGetConfigValueDefaultResponse,
+ TError = unknown,
+ TQueryKey extends Array<unknown> = unknown[],
+>(
+ {
+ accept,
+ option,
+ section,
+ }: {
+ accept?: "application/json" | "text/plain" | "*/*";
+ option: string;
+ section: string;
},
queryKey?: TQueryKey,
options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
) =>
useSuspenseQuery<TData, TError>({
- queryKey: Common.UseDashboardServiceHistoricalMetricsKeyFn(
- { endDate, startDate },
+ queryKey: Common.UseConfigServiceGetConfigValueKeyFn(
+ { accept, option, section },
queryKey,
),
queryFn: () =>
- DashboardService.historicalMetrics({ endDate, startDate }) as TData,
+ ConfigService.getConfigValue({ accept, option, section }) as TData,
...options,
});
/**
@@ -412,88 +465,80 @@ export const useDagsServiceRecentDagRunsSuspense = <
...options,
});
/**
- * Get Configs
- * Get configs for UI.
- * @returns ConfigResponse Successful Response
- * @throws ApiError
- */
-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 Config
+ * Historical Metrics
+ * Return cluster activity historical metrics.
* @param data The data for the request.
- * @param data.section
- * @param data.accept
- * @returns Config Successful Response
+ * @param data.startDate
+ * @param data.endDate
+ * @returns HistoricalMetricDataResponse Successful Response
* @throws ApiError
*/
-export const useConfigServiceGetConfigSuspense = <
- TData = Common.ConfigServiceGetConfigDefaultResponse,
+export const useDashboardServiceHistoricalMetricsSuspense = <
+ TData = Common.DashboardServiceHistoricalMetricsDefaultResponse,
TError = unknown,
TQueryKey extends Array<unknown> = unknown[],
>(
{
- accept,
- section,
+ endDate,
+ startDate,
}: {
- accept?: "application/json" | "text/plain" | "*/*";
- section?: string;
- } = {},
+ endDate?: string;
+ startDate: string;
+ },
queryKey?: TQueryKey,
options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
) =>
useSuspenseQuery<TData, TError>({
- queryKey: Common.UseConfigServiceGetConfigKeyFn(
- { accept, section },
+ queryKey: Common.UseDashboardServiceHistoricalMetricsKeyFn(
+ { endDate, startDate },
queryKey,
),
- queryFn: () => ConfigService.getConfig({ accept, section }) as TData,
+ queryFn: () =>
+ DashboardService.historicalMetrics({ endDate, startDate }) as TData,
...options,
});
/**
- * Get Config Value
+ * Graph Data
+ * Get Graph Data.
* @param data The data for the request.
- * @param data.section
- * @param data.option
- * @param data.accept
- * @returns Config Successful Response
+ * @param data.dagId
+ * @param data.root
+ * @param data.includeUpstream
+ * @param data.includeDownstream
+ * @returns GraphDataResponse Successful Response
* @throws ApiError
*/
-export const useConfigServiceGetConfigValueSuspense = <
- TData = Common.ConfigServiceGetConfigValueDefaultResponse,
+export const useGraphServiceGraphDataSuspense = <
+ TData = Common.GraphServiceGraphDataDefaultResponse,
TError = unknown,
TQueryKey extends Array<unknown> = unknown[],
>(
{
- accept,
- option,
- section,
+ dagId,
+ includeDownstream,
+ includeUpstream,
+ root,
}: {
- accept?: "application/json" | "text/plain" | "*/*";
- option: string;
- section: string;
+ dagId: string;
+ includeDownstream?: boolean;
+ includeUpstream?: boolean;
+ root?: string;
},
queryKey?: TQueryKey,
options?: Omit<UseQueryOptions<TData, TError>, "queryKey" | "queryFn">,
) =>
useSuspenseQuery<TData, TError>({
- queryKey: Common.UseConfigServiceGetConfigValueKeyFn(
- { accept, option, section },
+ queryKey: Common.UseGraphServiceGraphDataKeyFn(
+ { dagId, includeDownstream, includeUpstream, root },
queryKey,
),
queryFn: () =>
- ConfigService.getConfigValue({ accept, option, section }) as TData,
+ GraphService.graphData({
+ dagId,
+ includeDownstream,
+ includeUpstream,
+ root,
+ }) as TData,
...options,
});
/**
diff --git a/airflow/ui/openapi-gen/requests/schemas.gen.ts
b/airflow/ui/openapi-gen/requests/schemas.gen.ts
index 84c63a7d7bc..b9289674a18 100644
--- a/airflow/ui/openapi-gen/requests/schemas.gen.ts
+++ b/airflow/ui/openapi-gen/requests/schemas.gen.ts
@@ -2596,6 +2596,45 @@ This is the set of allowable values for the
\`\`warning_type\`\` field
in the DagWarning model.`,
} as const;
+export const $EdgeResponse = {
+ properties: {
+ is_setup_teardown: {
+ anyOf: [
+ {
+ type: "boolean",
+ },
+ {
+ type: "null",
+ },
+ ],
+ title: "Is Setup Teardown",
+ },
+ label: {
+ anyOf: [
+ {
+ type: "string",
+ },
+ {
+ type: "null",
+ },
+ ],
+ title: "Label",
+ },
+ source_id: {
+ type: "string",
+ title: "Source Id",
+ },
+ target_id: {
+ type: "string",
+ title: "Target Id",
+ },
+ },
+ type: "object",
+ required: ["source_id", "target_id"],
+ title: "EdgeResponse",
+ description: "Edge serializer for responses.",
+} as const;
+
export const $EventLogCollectionResponse = {
properties: {
event_logs: {
@@ -2777,6 +2816,30 @@ export const $FastAPIAppResponse = {
description: "Serializer for Plugin FastAPI App responses.",
} as const;
+export const $GraphDataResponse = {
+ properties: {
+ edges: {
+ items: {
+ $ref: "#/components/schemas/EdgeResponse",
+ },
+ type: "array",
+ title: "Edges",
+ },
+ nodes: {
+ $ref: "#/components/schemas/NodeResponse",
+ },
+ arrange: {
+ type: "string",
+ enum: ["BT", "LR", "RL", "TB"],
+ title: "Arrange",
+ },
+ },
+ type: "object",
+ required: ["edges", "nodes", "arrange"],
+ title: "GraphDataResponse",
+ description: "Graph Data serializer for responses.",
+} as const;
+
export const $HTTPExceptionResponse = {
properties: {
detail: {
@@ -3043,6 +3106,138 @@ export const $JobResponse = {
description: "Job serializer for responses.",
} as const;
+export const $NodeResponse = {
+ properties: {
+ children: {
+ anyOf: [
+ {
+ items: {
+ $ref: "#/components/schemas/NodeResponse",
+ },
+ type: "array",
+ },
+ {
+ type: "null",
+ },
+ ],
+ title: "Children",
+ },
+ id: {
+ anyOf: [
+ {
+ type: "string",
+ },
+ {
+ type: "null",
+ },
+ ],
+ title: "Id",
+ },
+ value: {
+ $ref: "#/components/schemas/NodeValueResponse",
+ },
+ },
+ type: "object",
+ required: ["id", "value"],
+ title: "NodeResponse",
+ description: "Node serializer for responses.",
+} as const;
+
+export const $NodeValueResponse = {
+ properties: {
+ isMapped: {
+ anyOf: [
+ {
+ type: "boolean",
+ },
+ {
+ type: "null",
+ },
+ ],
+ title: "Ismapped",
+ },
+ label: {
+ anyOf: [
+ {
+ type: "string",
+ },
+ {
+ type: "null",
+ },
+ ],
+ title: "Label",
+ },
+ labelStyle: {
+ anyOf: [
+ {
+ type: "string",
+ },
+ {
+ type: "null",
+ },
+ ],
+ title: "Labelstyle",
+ },
+ style: {
+ anyOf: [
+ {
+ type: "string",
+ },
+ {
+ type: "null",
+ },
+ ],
+ title: "Style",
+ },
+ tooltip: {
+ anyOf: [
+ {
+ type: "string",
+ },
+ {
+ type: "null",
+ },
+ ],
+ title: "Tooltip",
+ },
+ rx: {
+ type: "integer",
+ title: "Rx",
+ },
+ ry: {
+ type: "integer",
+ title: "Ry",
+ },
+ clusterLabelPos: {
+ anyOf: [
+ {
+ type: "string",
+ },
+ {
+ type: "null",
+ },
+ ],
+ title: "Clusterlabelpos",
+ },
+ setupTeardownType: {
+ anyOf: [
+ {
+ type: "string",
+ enum: ["setup", "teardown"],
+ },
+ {
+ type: "null",
+ },
+ ],
+ title: "Setupteardowntype",
+ },
+ },
+ type: "object",
+ required: ["rx", "ry"],
+ title: "NodeValueResponse",
+ description: "Graph Node Value responses.",
+} as const;
+
export const $PatchTaskInstanceBody = {
properties: {
dry_run: {
diff --git a/airflow/ui/openapi-gen/requests/services.gen.ts
b/airflow/ui/openapi-gen/requests/services.gen.ts
index 4c8944447ce..f066d5103be 100644
--- a/airflow/ui/openapi-gen/requests/services.gen.ts
+++ b/airflow/ui/openapi-gen/requests/services.gen.ts
@@ -25,15 +25,17 @@ import type {
GetDagAssetQueuedEventResponse,
DeleteDagAssetQueuedEventData,
DeleteDagAssetQueuedEventResponse,
- HistoricalMetricsData,
- HistoricalMetricsResponse,
- RecentDagRunsData,
- RecentDagRunsResponse,
GetConfigsResponse,
GetConfigData,
GetConfigResponse,
GetConfigValueData,
GetConfigValueResponse,
+ RecentDagRunsData,
+ RecentDagRunsResponse,
+ HistoricalMetricsData,
+ HistoricalMetricsResponse,
+ GraphDataData,
+ GraphDataResponse2,
ListBackfillsData,
ListBackfillsResponse,
CreateBackfillData,
@@ -508,28 +510,80 @@ export class AssetService {
}
}
-export class DashboardService {
+export class ConfigService {
/**
- * Historical Metrics
- * Return cluster activity historical metrics.
+ * Get Configs
+ * Get configs for UI.
+ * @returns ConfigResponse Successful Response
+ * @throws ApiError
+ */
+ public static getConfigs(): CancelablePromise<GetConfigsResponse> {
+ return __request(OpenAPI, {
+ method: "GET",
+ url: "/ui/config",
+ errors: {
+ 404: "Not Found",
+ },
+ });
+ }
+
+ /**
+ * Get Config
* @param data The data for the request.
- * @param data.startDate
- * @param data.endDate
- * @returns HistoricalMetricDataResponse Successful Response
+ * @param data.section
+ * @param data.accept
+ * @returns Config Successful Response
* @throws ApiError
*/
- public static historicalMetrics(
- data: HistoricalMetricsData,
- ): CancelablePromise<HistoricalMetricsResponse> {
+ public static getConfig(
+ data: GetConfigData = {},
+ ): CancelablePromise<GetConfigResponse> {
return __request(OpenAPI, {
method: "GET",
- url: "/ui/dashboard/historical_metrics_data",
+ url: "/public/config",
+ headers: {
+ accept: data.accept,
+ },
query: {
- start_date: data.startDate,
- end_date: data.endDate,
+ section: data.section,
},
errors: {
- 400: "Bad Request",
+ 401: "Unauthorized",
+ 403: "Forbidden",
+ 404: "Not Found",
+ 406: "Not Acceptable",
+ 422: "Validation Error",
+ },
+ });
+ }
+
+ /**
+ * Get Config Value
+ * @param data The data for the request.
+ * @param data.section
+ * @param data.option
+ * @param data.accept
+ * @returns Config Successful Response
+ * @throws ApiError
+ */
+ public static getConfigValue(
+ data: GetConfigValueData,
+ ): CancelablePromise<GetConfigValueResponse> {
+ return __request(OpenAPI, {
+ method: "GET",
+ url: "/public/config/section/{section}/option/{option}",
+ path: {
+ section: data.section,
+ option: data.option,
+ },
+ headers: {
+ accept: data.accept,
+ },
+ errors: {
+ 401: "Unauthorized",
+ 403: "Forbidden",
+ 404: "Not Found",
+ 406: "Not Acceptable",
422: "Validation Error",
},
});
@@ -579,80 +633,60 @@ export class DagsService {
}
}
-export class ConfigService {
- /**
- * Get Configs
- * Get configs for UI.
- * @returns ConfigResponse Successful Response
- * @throws ApiError
- */
- public static getConfigs(): CancelablePromise<GetConfigsResponse> {
- return __request(OpenAPI, {
- method: "GET",
- url: "/ui/config",
- errors: {
- 404: "Not Found",
- },
- });
- }
-
+export class DashboardService {
/**
- * Get Config
+ * Historical Metrics
+ * Return cluster activity historical metrics.
* @param data The data for the request.
- * @param data.section
- * @param data.accept
- * @returns Config Successful Response
+ * @param data.startDate
+ * @param data.endDate
+ * @returns HistoricalMetricDataResponse Successful Response
* @throws ApiError
*/
- public static getConfig(
- data: GetConfigData = {},
- ): CancelablePromise<GetConfigResponse> {
+ public static historicalMetrics(
+ data: HistoricalMetricsData,
+ ): CancelablePromise<HistoricalMetricsResponse> {
return __request(OpenAPI, {
method: "GET",
- url: "/public/config",
- headers: {
- accept: data.accept,
- },
+ url: "/ui/dashboard/historical_metrics_data",
query: {
- section: data.section,
+ start_date: data.startDate,
+ end_date: data.endDate,
},
errors: {
- 401: "Unauthorized",
- 403: "Forbidden",
- 404: "Not Found",
- 406: "Not Acceptable",
+ 400: "Bad Request",
422: "Validation Error",
},
});
}
+}
+export class GraphService {
/**
- * Get Config Value
+ * Graph Data
+ * Get Graph Data.
* @param data The data for the request.
- * @param data.section
- * @param data.option
- * @param data.accept
- * @returns Config Successful Response
+ * @param data.dagId
+ * @param data.root
+ * @param data.includeUpstream
+ * @param data.includeDownstream
+ * @returns GraphDataResponse Successful Response
* @throws ApiError
*/
- public static getConfigValue(
- data: GetConfigValueData,
- ): CancelablePromise<GetConfigValueResponse> {
+ public static graphData(
+ data: GraphDataData,
+ ): CancelablePromise<GraphDataResponse2> {
return __request(OpenAPI, {
method: "GET",
- url: "/public/config/section/{section}/option/{option}",
- path: {
- section: data.section,
- option: data.option,
- },
- headers: {
- accept: data.accept,
+ url: "/ui/graph/graph_data",
+ query: {
+ dag_id: data.dagId,
+ root: data.root,
+ include_upstream: data.includeUpstream,
+ include_downstream: data.includeDownstream,
},
errors: {
- 401: "Unauthorized",
- 403: "Forbidden",
- 404: "Not Found",
- 406: "Not Acceptable",
+ 400: "Bad Request",
422: "Validation Error",
},
});
diff --git a/airflow/ui/openapi-gen/requests/types.gen.ts
b/airflow/ui/openapi-gen/requests/types.gen.ts
index 1adcdc8eba8..1f3c450625c 100644
--- a/airflow/ui/openapi-gen/requests/types.gen.ts
+++ b/airflow/ui/openapi-gen/requests/types.gen.ts
@@ -620,6 +620,16 @@ export type DagTagPydantic = {
*/
export type DagWarningType = "asset conflict" | "non-existent pool";
+/**
+ * Edge serializer for responses.
+ */
+export type EdgeResponse = {
+ is_setup_teardown?: boolean | null;
+ label?: string | null;
+ source_id: string;
+ target_id: string;
+};
+
/**
* Event Log Collection Response.
*/
@@ -662,6 +672,17 @@ export type FastAPIAppResponse = {
[key: string]: unknown | string;
};
+/**
+ * Graph Data serializer for responses.
+ */
+export type GraphDataResponse = {
+ edges: Array<EdgeResponse>;
+ nodes: NodeResponse;
+ arrange: "BT" | "LR" | "RL" | "TB";
+};
+
+export type arrange = "BT" | "LR" | "RL" | "TB";
+
/**
* HTTPException Model used for error response.
*/
@@ -738,6 +759,30 @@ export type JobResponse = {
unixname: string | null;
};
+/**
+ * Node serializer for responses.
+ */
+export type NodeResponse = {
+ children?: Array<NodeResponse> | null;
+ id: string | null;
+ value: NodeValueResponse;
+};
+
+/**
+ * Graph Node Value responses.
+ */
+export type NodeValueResponse = {
+ isMapped?: boolean | null;
+ label?: string | null;
+ labelStyle?: string | null;
+ style?: string | null;
+ tooltip?: string | null;
+ rx: number;
+ ry: number;
+ clusterLabelPos?: string | null;
+ setupTeardownType?: "setup" | "teardown" | null;
+};
+
/**
* Request body for Clear Task Instances endpoint.
*/
@@ -1333,12 +1378,22 @@ export type DeleteDagAssetQueuedEventData = {
export type DeleteDagAssetQueuedEventResponse = void;
-export type HistoricalMetricsData = {
- endDate?: string | null;
- startDate: string;
+export type GetConfigsResponse = ConfigResponse;
+
+export type GetConfigData = {
+ accept?: "application/json" | "text/plain" | "*/*";
+ section?: string | null;
};
-export type HistoricalMetricsResponse = HistoricalMetricDataResponse;
+export type GetConfigResponse = Config;
+
+export type GetConfigValueData = {
+ accept?: "application/json" | "text/plain" | "*/*";
+ option: string;
+ section: string;
+};
+
+export type GetConfigValueResponse = Config;
export type RecentDagRunsData = {
dagDisplayNamePattern?: string | null;
@@ -1355,22 +1410,21 @@ export type RecentDagRunsData = {
export type RecentDagRunsResponse = DAGWithLatestDagRunsCollectionResponse;
-export type GetConfigsResponse = ConfigResponse;
-
-export type GetConfigData = {
- accept?: "application/json" | "text/plain" | "*/*";
- section?: string | null;
+export type HistoricalMetricsData = {
+ endDate?: string | null;
+ startDate: string;
};
-export type GetConfigResponse = Config;
+export type HistoricalMetricsResponse = HistoricalMetricDataResponse;
-export type GetConfigValueData = {
- accept?: "application/json" | "text/plain" | "*/*";
- option: string;
- section: string;
+export type GraphDataData = {
+ dagId: string;
+ includeDownstream?: boolean;
+ includeUpstream?: boolean;
+ root?: string | null;
};
-export type GetConfigValueResponse = Config;
+export type GraphDataResponse2 = GraphDataResponse;
export type ListBackfillsData = {
dagId: string;
@@ -2272,40 +2326,6 @@ export type $OpenApiTs = {
};
};
};
- "/ui/dashboard/historical_metrics_data": {
- get: {
- req: HistoricalMetricsData;
- res: {
- /**
- * Successful Response
- */
- 200: HistoricalMetricDataResponse;
- /**
- * Bad Request
- */
- 400: HTTPExceptionResponse;
- /**
- * Validation Error
- */
- 422: HTTPValidationError;
- };
- };
- };
- "/ui/dags/recent_dag_runs": {
- get: {
- req: RecentDagRunsData;
- res: {
- /**
- * Successful Response
- */
- 200: DAGWithLatestDagRunsCollectionResponse;
- /**
- * Validation Error
- */
- 422: HTTPValidationError;
- };
- };
- };
"/ui/config": {
get: {
res: {
@@ -2382,6 +2402,59 @@ export type $OpenApiTs = {
};
};
};
+ "/ui/dags/recent_dag_runs": {
+ get: {
+ req: RecentDagRunsData;
+ res: {
+ /**
+ * Successful Response
+ */
+ 200: DAGWithLatestDagRunsCollectionResponse;
+ /**
+ * Validation Error
+ */
+ 422: HTTPValidationError;
+ };
+ };
+ };
+ "/ui/dashboard/historical_metrics_data": {
+ get: {
+ req: HistoricalMetricsData;
+ res: {
+ /**
+ * Successful Response
+ */
+ 200: HistoricalMetricDataResponse;
+ /**
+ * Bad Request
+ */
+ 400: HTTPExceptionResponse;
+ /**
+ * Validation Error
+ */
+ 422: HTTPValidationError;
+ };
+ };
+ };
+ "/ui/graph/graph_data": {
+ get: {
+ req: GraphDataData;
+ res: {
+ /**
+ * Successful Response
+ */
+ 200: GraphDataResponse;
+ /**
+ * Bad Request
+ */
+ 400: HTTPExceptionResponse;
+ /**
+ * Validation Error
+ */
+ 422: HTTPValidationError;
+ };
+ };
+ };
"/public/backfills": {
get: {
req: ListBackfillsData;
diff --git a/tests/api_fastapi/core_api/routes/ui/test_graph.py
b/tests/api_fastapi/core_api/routes/ui/test_graph.py
new file mode 100644
index 00000000000..85dabd3ac6a
--- /dev/null
+++ b/tests/api_fastapi/core_api/routes/ui/test_graph.py
@@ -0,0 +1,198 @@
+#
+# 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 pendulum
+import pytest
+
+from airflow.models import DagBag
+from airflow.operators.empty import EmptyOperator
+
+from tests_common.test_utils.db import clear_db_runs
+
+pytestmark = pytest.mark.db_test
+
+DAG_ID = "test_dag_id"
+
+
[email protected](autouse=True, scope="module")
+def examples_dag_bag():
+ # Speed up: We don't want example dags for this module
+
+ return DagBag(include_examples=False, read_dags_from_db=True)
+
+
[email protected](autouse=True)
+def clean():
+ clear_db_runs()
+ yield
+ clear_db_runs()
+
+
[email protected]
+def make_dag(dag_maker, session, time_machine):
+ with dag_maker(
+ dag_id=DAG_ID,
+ serialized=True,
+ session=session,
+ start_date=pendulum.DateTime(2023, 2, 1, 0, 0, 0, tzinfo=pendulum.UTC),
+ ):
+ EmptyOperator(task_id="task_1") >> EmptyOperator(task_id="task_2")
+
+ dag_maker.dagbag.sync_to_db()
+
+
+class TestGraphDataEndpoint:
+ @pytest.mark.parametrize(
+ "params, expected",
+ [
+ (
+ {"dag_id": DAG_ID},
+ {
+ "arrange": "LR",
+ "edges": [
+ {
+ "is_setup_teardown": None,
+ "label": None,
+ "source_id": "task_1",
+ "target_id": "task_2",
+ },
+ ],
+ "nodes": {
+ "children": [
+ {
+ "children": None,
+ "id": "task_1",
+ "value": {
+ "clusterLabelPos": None,
+ "isMapped": None,
+ "label": "task_1",
+ "labelStyle": "fill:#000;",
+ "rx": 5,
+ "ry": 5,
+ "setupTeardownType": None,
+ "style": "fill:#e8f7e4;",
+ "tooltip": None,
+ },
+ },
+ {
+ "children": None,
+ "id": "task_2",
+ "value": {
+ "clusterLabelPos": None,
+ "isMapped": None,
+ "label": "task_2",
+ "labelStyle": "fill:#000;",
+ "rx": 5,
+ "ry": 5,
+ "setupTeardownType": None,
+ "style": "fill:#e8f7e4;",
+ "tooltip": None,
+ },
+ },
+ ],
+ "id": None,
+ "value": {
+ "clusterLabelPos": "top",
+ "isMapped": False,
+ "label": None,
+ "labelStyle": "fill:#000;",
+ "rx": 5,
+ "ry": 5,
+ "setupTeardownType": None,
+ "style": "fill:CornflowerBlue",
+ "tooltip": "",
+ },
+ },
+ },
+ ),
+ (
+ {
+ "dag_id": DAG_ID,
+ "root": "unknown_task",
+ },
+ {
+ "arrange": "LR",
+ "edges": [],
+ "nodes": {
+ "children": [],
+ "id": None,
+ "value": {
+ "clusterLabelPos": "top",
+ "isMapped": False,
+ "label": None,
+ "labelStyle": "fill:#000;",
+ "rx": 5,
+ "ry": 5,
+ "setupTeardownType": None,
+ "style": "fill:CornflowerBlue",
+ "tooltip": "",
+ },
+ },
+ },
+ ),
+ (
+ {
+ "dag_id": DAG_ID,
+ "root": "task_1",
+ "filter_upstream": False,
+ "filter_downstream": False,
+ },
+ {
+ "arrange": "LR",
+ "edges": [],
+ "nodes": {
+ "children": [
+ {
+ "children": None,
+ "id": "task_1",
+ "value": {
+ "clusterLabelPos": None,
+ "isMapped": None,
+ "label": "task_1",
+ "labelStyle": "fill:#000;",
+ "rx": 5,
+ "ry": 5,
+ "setupTeardownType": None,
+ "style": "fill:#e8f7e4;",
+ "tooltip": None,
+ },
+ },
+ ],
+ "id": None,
+ "value": {
+ "clusterLabelPos": "top",
+ "isMapped": False,
+ "label": None,
+ "labelStyle": "fill:#000;",
+ "rx": 5,
+ "ry": 5,
+ "setupTeardownType": None,
+ "style": "fill:CornflowerBlue",
+ "tooltip": "",
+ },
+ },
+ },
+ ),
+ ],
+ )
+ @pytest.mark.usefixtures("make_dag")
+ def test_historical_metrics_data(self, test_client, params, expected):
+ response = test_client.get("/ui/graph/graph_data", params=params)
+ assert response.status_code == 200
+ assert response.json() == expected