diff --git a/airflow/api_connexion/endpoints/dag_source_endpoint.py b/airflow/api_connexion/endpoints/dag_source_endpoint.py index d7713106d1cd..9a3285884e7e 100644 --- a/airflow/api_connexion/endpoints/dag_source_endpoint.py +++ b/airflow/api_connexion/endpoints/dag_source_endpoint.py @@ -28,6 +28,7 @@ from airflow.auth.managers.models.resource_details import DagAccessEntity, DagDetails from airflow.models.dag import DagModel from airflow.models.dagcode import DagCode +from airflow.utils.api_migration import mark_fastapi_migration_done from airflow.utils.session import NEW_SESSION, provide_session from airflow.www.extensions.init_auth_manager import get_auth_manager @@ -37,6 +38,7 @@ from airflow.auth.managers.models.batch_apis import IsAuthorizedDagRequest +@mark_fastapi_migration_done @security.requires_access_dag("GET", DagAccessEntity.CODE) @provide_session def get_dag_source(*, file_token: str, session: Session = NEW_SESSION) -> Response: diff --git a/airflow/api_fastapi/app.py b/airflow/api_fastapi/app.py index 9c3e5a3bd798..43885724564c 100644 --- a/airflow/api_fastapi/app.py +++ b/airflow/api_fastapi/app.py @@ -19,9 +19,8 @@ import logging from fastapi import FastAPI -from fastapi.middleware.cors import CORSMiddleware -from airflow.api_fastapi.core_api.app import init_dag_bag, init_plugins, init_views +from airflow.api_fastapi.core_api.app import init_config, init_dag_bag, init_plugins, init_views from airflow.api_fastapi.execution_api.app import create_task_execution_api_app log = logging.getLogger(__name__) @@ -30,8 +29,6 @@ def create_app(apps: str = "all") -> FastAPI: - from airflow.configuration import conf - apps_list = apps.split(",") if apps else ["all"] app = FastAPI( @@ -50,18 +47,7 @@ def create_app(apps: str = "all") -> FastAPI: task_exec_api_app = create_task_execution_api_app(app) app.mount("/execution", task_exec_api_app) - allow_origins = conf.getlist("api", "access_control_allow_origins") - allow_methods = conf.getlist("api", "access_control_allow_methods") - allow_headers = conf.getlist("api", "access_control_allow_headers") - - if allow_origins or allow_methods or allow_headers: - app.add_middleware( - CORSMiddleware, - allow_origins=allow_origins, - allow_credentials=True, - allow_methods=allow_methods, - allow_headers=allow_headers, - ) + init_config(app) return app diff --git a/airflow/api_fastapi/core_api/app.py b/airflow/api_fastapi/core_api/app.py index f47a33227f36..47927ad6fbbb 100644 --- a/airflow/api_fastapi/core_api/app.py +++ b/airflow/api_fastapi/core_api/app.py @@ -22,6 +22,7 @@ from typing import cast from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware from starlette.requests import Request from starlette.responses import HTMLResponse from starlette.staticfiles import StaticFiles @@ -94,3 +95,22 @@ def init_plugins(app: FastAPI) -> None: log.debug("Adding subapplication %s under prefix %s", name, url_prefix) app.mount(url_prefix, subapp) + + +def init_config(app: FastAPI) -> None: + from airflow.configuration import conf + + allow_origins = conf.getlist("api", "access_control_allow_origins") + allow_methods = conf.getlist("api", "access_control_allow_methods") + allow_headers = conf.getlist("api", "access_control_allow_headers") + + if allow_origins or allow_methods or allow_headers: + app.add_middleware( + CORSMiddleware, + allow_origins=allow_origins, + allow_credentials=True, + allow_methods=allow_methods, + allow_headers=allow_headers, + ) + + app.state.secret_key = conf.get("webserver", "secret_key") diff --git a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml index ae5fc9e11773..42e371a2c0b3 100644 --- a/airflow/api_fastapi/core_api/openapi/v1-generated.yaml +++ b/airflow/api_fastapi/core_api/openapi/v1-generated.yaml @@ -170,6 +170,151 @@ paths: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' + /public/connections/{connection_id}: + delete: + tags: + - Connection + summary: Delete Connection + description: Delete a connection entry. + operationId: delete_connection + parameters: + - name: connection_id + in: path + required: true + schema: + type: string + title: Connection Id + responses: + '204': + description: Successful Response + '401': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Unauthorized + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Forbidden + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Not Found + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + get: + tags: + - Connection + summary: Get Connection + description: Get a connection entry. + operationId: get_connection + parameters: + - name: connection_id + in: path + required: true + schema: + type: string + title: Connection Id + responses: + '200': + description: Successful Response + content: + application/json: + schema: + $ref: '#/components/schemas/ConnectionResponse' + '401': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Unauthorized + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Forbidden + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Not Found + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + /public/connections/: + get: + tags: + - Connection + summary: Get Connections + description: Get all connection entries. + operationId: get_connections + parameters: + - name: limit + in: query + required: false + schema: + type: integer + default: 100 + title: Limit + - name: offset + in: query + required: false + schema: + type: integer + default: 0 + title: Offset + - name: order_by + in: query + required: false + schema: + type: string + default: id + title: Order By + responses: + '200': + description: Successful Response + content: + application/json: + schema: + $ref: '#/components/schemas/ConnectionCollectionResponse' + '401': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Unauthorized + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Forbidden + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Not Found + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' /public/dags/: get: tags: @@ -667,23 +812,32 @@ paths: schema: $ref: '#/components/schemas/HTTPExceptionResponse' description: Unprocessable Entity - /public/connections/{connection_id}: - delete: + /public/dags/{dag_id}/dagRuns/{dag_run_id}: + get: tags: - - Connection - summary: Delete Connection - description: Delete a connection entry. - operationId: delete_connection + - DagRun + summary: Get Dag Run + operationId: get_dag_run parameters: - - name: connection_id + - name: dag_id in: path required: true schema: type: string - title: Connection Id + title: Dag Id + - name: dag_run_id + in: path + required: true + schema: + type: string + title: Dag Run Id responses: - '204': + '200': description: Successful Response + content: + application/json: + schema: + $ref: '#/components/schemas/DAGRunResponse' '401': content: application/json: @@ -708,26 +862,34 @@ paths: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' - get: + delete: tags: - - Connection - summary: Get Connection - description: Get a connection entry. - operationId: get_connection + - DagRun + summary: Delete Dag Run + description: Delete a DAG Run entry. + operationId: delete_dag_run parameters: - - name: connection_id + - name: dag_id in: path required: true schema: type: string - title: Connection Id + title: Dag Id + - name: dag_run_id + in: path + required: true + schema: + type: string + title: Dag Run Id responses: - '200': + '204': description: Successful Response + '400': content: application/json: schema: - $ref: '#/components/schemas/ConnectionResponse' + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Bad Request '401': content: application/json: @@ -752,83 +914,54 @@ paths: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' - /public/connections/: - get: + patch: tags: - - Connection - summary: Get Connections - description: Get all connection entries. - operationId: get_connections + - DagRun + summary: Patch Dag Run State + description: Modify a DAG Run. + operationId: patch_dag_run_state parameters: - - name: limit - in: query - required: false + - name: dag_id + in: path + required: true schema: - type: integer - default: 100 - title: Limit - - name: offset - in: query - required: false + type: string + title: Dag Id + - name: dag_run_id + in: path + required: true schema: - type: integer - default: 0 - title: Offset - - name: order_by + type: string + title: Dag Run Id + - name: update_mask in: query required: false schema: - type: string - default: id - title: Order By + anyOf: + - type: array + items: + type: string + - type: 'null' + title: Update Mask + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/DAGRunPatchBody' responses: '200': description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/ConnectionCollectionResponse' - '401': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Unauthorized - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Forbidden - '404': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Not Found - '422': - description: Validation Error - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPValidationError' - /public/variables/{variable_key}: - delete: - tags: - - Variable - summary: Delete Variable - description: Delete a variable entry. - operationId: delete_variable - parameters: - - name: variable_key - in: path - required: true - schema: - type: string - title: Variable Key - responses: - '204': - description: Successful Response + $ref: '#/components/schemas/DAGRunResponse' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Bad Request '401': content: application/json: @@ -853,351 +986,38 @@ paths: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' + /public/dagSources/{file_token}: get: tags: - - Variable - summary: Get Variable - description: Get a variable entry. - operationId: get_variable + - DagSource + summary: Get Dag Source + description: Get source code using file token. + operationId: get_dag_source parameters: - - name: variable_key + - name: file_token in: path required: true schema: type: string - title: Variable Key - responses: - '200': - description: Successful Response - content: - application/json: - schema: - $ref: '#/components/schemas/VariableResponse' - '401': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Unauthorized - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Forbidden - '404': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Not Found - '422': - description: Validation Error - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPValidationError' - patch: - tags: - - Variable - summary: Patch Variable - description: Update a variable by key. - operationId: patch_variable - parameters: - - name: variable_key - in: path - required: true - schema: - type: string - title: Variable Key - - name: update_mask - in: query - required: false - schema: - anyOf: - - type: array - items: - type: string - - type: 'null' - title: Update Mask - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/VariableBody' - responses: - '200': - description: Successful Response - content: - application/json: - schema: - $ref: '#/components/schemas/VariableResponse' - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Bad Request - '401': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Unauthorized - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Forbidden - '404': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Not Found - '422': - description: Validation Error - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPValidationError' - /public/variables/: - get: - tags: - - Variable - summary: Get Variables - description: Get all Variables entries. - operationId: get_variables - parameters: - - name: limit - in: query - required: false - schema: - type: integer - default: 100 - title: Limit - - name: offset - in: query - required: false - schema: - type: integer - default: 0 - title: Offset - - name: order_by - in: query - required: false - schema: - type: string - default: id - title: Order By - responses: - '200': - description: Successful Response - content: - application/json: - schema: - $ref: '#/components/schemas/VariableCollectionResponse' - '401': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Unauthorized - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Forbidden - '422': - description: Validation Error - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPValidationError' - post: - tags: - - Variable - summary: Post Variable - description: Create a variable. - operationId: post_variable - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/VariableBody' - responses: - '201': - description: Successful Response - content: - application/json: - schema: - $ref: '#/components/schemas/VariableResponse' - '401': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Unauthorized - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Forbidden - '422': - description: Validation Error - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPValidationError' - /public/dags/{dag_id}/dagRuns/{dag_run_id}: - get: - tags: - - DagRun - summary: Get Dag Run - operationId: get_dag_run - parameters: - - name: dag_id - in: path - required: true - schema: - type: string - title: Dag Id - - name: dag_run_id - in: path - required: true - schema: - type: string - title: Dag Run Id - responses: - '200': - description: Successful Response - content: - application/json: - schema: - $ref: '#/components/schemas/DAGRunResponse' - '401': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Unauthorized - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Forbidden - '404': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Not Found - '422': - description: Validation Error - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPValidationError' - delete: - tags: - - DagRun - summary: Delete Dag Run - description: Delete a DAG Run entry. - operationId: delete_dag_run - parameters: - - name: dag_id - in: path - required: true - schema: - type: string - title: Dag Id - - name: dag_run_id - in: path - required: true - schema: - type: string - title: Dag Run Id - responses: - '204': - description: Successful Response - '400': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Bad Request - '401': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Unauthorized - '403': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Forbidden - '404': - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPExceptionResponse' - description: Not Found - '422': - description: Validation Error - content: - application/json: - schema: - $ref: '#/components/schemas/HTTPValidationError' - patch: - tags: - - DagRun - summary: Patch Dag Run State - description: Modify a DAG Run. - operationId: patch_dag_run_state - parameters: - - name: dag_id - in: path - required: true - schema: - type: string - title: Dag Id - - name: dag_run_id - in: path - required: true - schema: - type: string - title: Dag Run Id - - name: update_mask - in: query + title: File Token + - name: accept + in: header required: false schema: - anyOf: - - type: array - items: - type: string - - type: 'null' - title: Update Mask - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/DAGRunPatchBody' + type: string + default: '*/*' + title: Accept responses: '200': description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/DAGRunResponse' + $ref: '#/components/schemas/DAGSourceResponse' + text/plain: + schema: + type: string + example: dag code '400': content: application/json: @@ -1222,6 +1042,12 @@ paths: 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: @@ -1622,6 +1448,248 @@ paths: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' + /public/variables/{variable_key}: + delete: + tags: + - Variable + summary: Delete Variable + description: Delete a variable entry. + operationId: delete_variable + parameters: + - name: variable_key + in: path + required: true + schema: + type: string + title: Variable Key + responses: + '204': + description: Successful Response + '401': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Unauthorized + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Forbidden + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Not Found + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + get: + tags: + - Variable + summary: Get Variable + description: Get a variable entry. + operationId: get_variable + parameters: + - name: variable_key + in: path + required: true + schema: + type: string + title: Variable Key + responses: + '200': + description: Successful Response + content: + application/json: + schema: + $ref: '#/components/schemas/VariableResponse' + '401': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Unauthorized + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Forbidden + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Not Found + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + patch: + tags: + - Variable + summary: Patch Variable + description: Update a variable by key. + operationId: patch_variable + parameters: + - name: variable_key + in: path + required: true + schema: + type: string + title: Variable Key + - name: update_mask + in: query + required: false + schema: + anyOf: + - type: array + items: + type: string + - type: 'null' + title: Update Mask + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/VariableBody' + responses: + '200': + description: Successful Response + content: + application/json: + schema: + $ref: '#/components/schemas/VariableResponse' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Bad Request + '401': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Unauthorized + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Forbidden + '404': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Not Found + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + /public/variables/: + get: + tags: + - Variable + summary: Get Variables + description: Get all Variables entries. + operationId: get_variables + parameters: + - name: limit + in: query + required: false + schema: + type: integer + default: 100 + title: Limit + - name: offset + in: query + required: false + schema: + type: integer + default: 0 + title: Offset + - name: order_by + in: query + required: false + schema: + type: string + default: id + title: Order By + responses: + '200': + description: Successful Response + content: + application/json: + schema: + $ref: '#/components/schemas/VariableCollectionResponse' + '401': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Unauthorized + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Forbidden + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' + post: + tags: + - Variable + summary: Post Variable + description: Create a variable. + operationId: post_variable + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/VariableBody' + responses: + '201': + description: Successful Response + content: + application/json: + schema: + $ref: '#/components/schemas/VariableResponse' + '401': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Unauthorized + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPExceptionResponse' + description: Forbidden + '422': + description: Validation Error + content: + application/json: + schema: + $ref: '#/components/schemas/HTTPValidationError' components: schemas: AppBuilderMenuItemResponse: @@ -2293,6 +2361,18 @@ components: - asset_triggered title: DAGRunTypes description: DAG Run Types for responses. + DAGSourceResponse: + properties: + content: + anyOf: + - type: string + - type: 'null' + title: Content + type: object + required: + - content + title: DAGSourceResponse + description: DAG Source serializer for responses. DAGTagCollectionResponse: properties: tags: diff --git a/airflow/api_fastapi/core_api/routes/public/__init__.py b/airflow/api_fastapi/core_api/routes/public/__init__.py index fe32ecc9e27d..1c2cc698fcdd 100644 --- a/airflow/api_fastapi/core_api/routes/public/__init__.py +++ b/airflow/api_fastapi/core_api/routes/public/__init__.py @@ -20,6 +20,7 @@ from airflow.api_fastapi.common.router import AirflowRouter from airflow.api_fastapi.core_api.routes.public.connections import connections_router from airflow.api_fastapi.core_api.routes.public.dag_run import dag_run_router +from airflow.api_fastapi.core_api.routes.public.dag_sources import dag_sources_router from airflow.api_fastapi.core_api.routes.public.dags import dags_router from airflow.api_fastapi.core_api.routes.public.event_logs import event_logs_router from airflow.api_fastapi.core_api.routes.public.monitor import monitor_router @@ -32,13 +33,14 @@ public_router = AirflowRouter(prefix="/public") -public_router.include_router(dags_router) public_router.include_router(connections_router) -public_router.include_router(variables_router) +public_router.include_router(dags_router) public_router.include_router(dag_run_router) +public_router.include_router(dag_sources_router) public_router.include_router(monitor_router) public_router.include_router(pools_router) public_router.include_router(providers_router) public_router.include_router(plugins_router) public_router.include_router(version_router) public_router.include_router(event_logs_router) +public_router.include_router(variables_router) diff --git a/airflow/api_fastapi/core_api/routes/public/dag_sources.py b/airflow/api_fastapi/core_api/routes/public/dag_sources.py new file mode 100644 index 000000000000..2a660a7d0264 --- /dev/null +++ b/airflow/api_fastapi/core_api/routes/public/dag_sources.py @@ -0,0 +1,71 @@ +# 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, Header, HTTPException, Request, Response +from itsdangerous import BadSignature, URLSafeSerializer +from sqlalchemy.orm import Session +from typing_extensions import Annotated + +from airflow.api_fastapi.common.db.common import get_session +from airflow.api_fastapi.common.router import AirflowRouter +from airflow.api_fastapi.core_api.openapi.exceptions import create_openapi_http_exception_doc +from airflow.api_fastapi.core_api.serializers.dag_sources import DAGSourceResponse +from airflow.models.dagcode import DagCode + +dag_sources_router = AirflowRouter(tags=["DagSource"], prefix="/dagSources") + +mime_type_text = "text/plain" +mime_type_json = "application/json" +mime_type_any = "*/*" + + +@dag_sources_router.get( + "/{file_token}", + responses={ + **create_openapi_http_exception_doc([400, 401, 403, 404, 406]), + "200": { + "description": "Successful Response", + "content": { + mime_type_text: {"schema": {"type": "string", "example": "dag code"}}, + }, + }, + }, + response_model=DAGSourceResponse, +) +async def get_dag_source( + file_token: str, + session: Annotated[Session, Depends(get_session)], + request: Request, + accept: Annotated[str, Header()] = mime_type_any, +): + """Get source code using file token.""" + auth_s = URLSafeSerializer(request.app.state.secret_key) + + try: + path = auth_s.loads(file_token) + dag_source_model = DAGSourceResponse( + content=DagCode.code(path, session=session), + ) + except (BadSignature, FileNotFoundError): + raise HTTPException(404, "DAG source not found") + + if accept.startswith(mime_type_text): + return Response(dag_source_model.content, media_type=mime_type_text) + if accept.startswith(mime_type_json) or accept.startswith(mime_type_any): + return dag_source_model + raise HTTPException(406, "Content not available for Accept header") diff --git a/airflow/api_fastapi/core_api/serializers/dag_sources.py b/airflow/api_fastapi/core_api/serializers/dag_sources.py new file mode 100644 index 000000000000..8cae02be1a85 --- /dev/null +++ b/airflow/api_fastapi/core_api/serializers/dag_sources.py @@ -0,0 +1,25 @@ +# 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 pydantic import BaseModel + + +class DAGSourceResponse(BaseModel): + """DAG Source serializer for responses.""" + + content: str | None diff --git a/airflow/ui/openapi-gen/queries/common.ts b/airflow/ui/openapi-gen/queries/common.ts index b8c83b1525b2..b05070962f02 100644 --- a/airflow/ui/openapi-gen/queries/common.ts +++ b/airflow/ui/openapi-gen/queries/common.ts @@ -6,6 +6,7 @@ import { ConnectionService, DagRunService, DagService, + DagSourceService, DagsService, DashboardService, EventLogService, @@ -106,6 +107,50 @@ export const UseDagsServiceRecentDagRunsKeyFn = ( }, ]), ]; +export type ConnectionServiceGetConnectionDefaultResponse = Awaited< + ReturnType +>; +export type ConnectionServiceGetConnectionQueryResult< + TData = ConnectionServiceGetConnectionDefaultResponse, + TError = unknown, +> = UseQueryResult; +export const useConnectionServiceGetConnectionKey = + "ConnectionServiceGetConnection"; +export const UseConnectionServiceGetConnectionKeyFn = ( + { + connectionId, + }: { + connectionId: string; + }, + queryKey?: Array, +) => [ + useConnectionServiceGetConnectionKey, + ...(queryKey ?? [{ connectionId }]), +]; +export type ConnectionServiceGetConnectionsDefaultResponse = Awaited< + ReturnType +>; +export type ConnectionServiceGetConnectionsQueryResult< + TData = ConnectionServiceGetConnectionsDefaultResponse, + TError = unknown, +> = UseQueryResult; +export const useConnectionServiceGetConnectionsKey = + "ConnectionServiceGetConnections"; +export const UseConnectionServiceGetConnectionsKeyFn = ( + { + limit, + offset, + orderBy, + }: { + limit?: number; + offset?: number; + orderBy?: string; + } = {}, + queryKey?: Array, +) => [ + useConnectionServiceGetConnectionsKey, + ...(queryKey ?? [{ limit, offset, orderBy }]), +]; export type DagServiceGetDagsDefaultResponse = Awaited< ReturnType >; @@ -213,89 +258,6 @@ export const UseDagServiceGetDagDetailsKeyFn = ( }, queryKey?: Array, ) => [useDagServiceGetDagDetailsKey, ...(queryKey ?? [{ dagId }])]; -export type ConnectionServiceGetConnectionDefaultResponse = Awaited< - ReturnType ->; -export type ConnectionServiceGetConnectionQueryResult< - TData = ConnectionServiceGetConnectionDefaultResponse, - TError = unknown, -> = UseQueryResult; -export const useConnectionServiceGetConnectionKey = - "ConnectionServiceGetConnection"; -export const UseConnectionServiceGetConnectionKeyFn = ( - { - connectionId, - }: { - connectionId: string; - }, - queryKey?: Array, -) => [ - useConnectionServiceGetConnectionKey, - ...(queryKey ?? [{ connectionId }]), -]; -export type ConnectionServiceGetConnectionsDefaultResponse = Awaited< - ReturnType ->; -export type ConnectionServiceGetConnectionsQueryResult< - TData = ConnectionServiceGetConnectionsDefaultResponse, - TError = unknown, -> = UseQueryResult; -export const useConnectionServiceGetConnectionsKey = - "ConnectionServiceGetConnections"; -export const UseConnectionServiceGetConnectionsKeyFn = ( - { - limit, - offset, - orderBy, - }: { - limit?: number; - offset?: number; - orderBy?: string; - } = {}, - queryKey?: Array, -) => [ - useConnectionServiceGetConnectionsKey, - ...(queryKey ?? [{ limit, offset, orderBy }]), -]; -export type VariableServiceGetVariableDefaultResponse = Awaited< - ReturnType ->; -export type VariableServiceGetVariableQueryResult< - TData = VariableServiceGetVariableDefaultResponse, - TError = unknown, -> = UseQueryResult; -export const useVariableServiceGetVariableKey = "VariableServiceGetVariable"; -export const UseVariableServiceGetVariableKeyFn = ( - { - variableKey, - }: { - variableKey: string; - }, - queryKey?: Array, -) => [useVariableServiceGetVariableKey, ...(queryKey ?? [{ variableKey }])]; -export type VariableServiceGetVariablesDefaultResponse = Awaited< - ReturnType ->; -export type VariableServiceGetVariablesQueryResult< - TData = VariableServiceGetVariablesDefaultResponse, - TError = unknown, -> = UseQueryResult; -export const useVariableServiceGetVariablesKey = "VariableServiceGetVariables"; -export const UseVariableServiceGetVariablesKeyFn = ( - { - limit, - offset, - orderBy, - }: { - limit?: number; - offset?: number; - orderBy?: string; - } = {}, - queryKey?: Array, -) => [ - useVariableServiceGetVariablesKey, - ...(queryKey ?? [{ limit, offset, orderBy }]), -]; export type DagRunServiceGetDagRunDefaultResponse = Awaited< ReturnType >; @@ -314,6 +276,28 @@ export const UseDagRunServiceGetDagRunKeyFn = ( }, queryKey?: Array, ) => [useDagRunServiceGetDagRunKey, ...(queryKey ?? [{ dagId, dagRunId }])]; +export type DagSourceServiceGetDagSourceDefaultResponse = Awaited< + ReturnType +>; +export type DagSourceServiceGetDagSourceQueryResult< + TData = DagSourceServiceGetDagSourceDefaultResponse, + TError = unknown, +> = UseQueryResult; +export const useDagSourceServiceGetDagSourceKey = + "DagSourceServiceGetDagSource"; +export const UseDagSourceServiceGetDagSourceKeyFn = ( + { + accept, + fileToken, + }: { + accept?: string; + fileToken: string; + }, + queryKey?: Array, +) => [ + useDagSourceServiceGetDagSourceKey, + ...(queryKey ?? [{ accept, fileToken }]), +]; export type MonitorServiceGetHealthDefaultResponse = Awaited< ReturnType >; @@ -426,35 +410,71 @@ export const UseEventLogServiceGetEventLogKeyFn = ( }, queryKey?: Array, ) => [useEventLogServiceGetEventLogKey, ...(queryKey ?? [{ eventLogId }])]; -export type VariableServicePostVariableMutationResult = Awaited< - ReturnType +export type VariableServiceGetVariableDefaultResponse = Awaited< + ReturnType +>; +export type VariableServiceGetVariableQueryResult< + TData = VariableServiceGetVariableDefaultResponse, + TError = unknown, +> = UseQueryResult; +export const useVariableServiceGetVariableKey = "VariableServiceGetVariable"; +export const UseVariableServiceGetVariableKeyFn = ( + { + variableKey, + }: { + variableKey: string; + }, + queryKey?: Array, +) => [useVariableServiceGetVariableKey, ...(queryKey ?? [{ variableKey }])]; +export type VariableServiceGetVariablesDefaultResponse = Awaited< + ReturnType >; +export type VariableServiceGetVariablesQueryResult< + TData = VariableServiceGetVariablesDefaultResponse, + TError = unknown, +> = UseQueryResult; +export const useVariableServiceGetVariablesKey = "VariableServiceGetVariables"; +export const UseVariableServiceGetVariablesKeyFn = ( + { + limit, + offset, + orderBy, + }: { + limit?: number; + offset?: number; + orderBy?: string; + } = {}, + queryKey?: Array, +) => [ + useVariableServiceGetVariablesKey, + ...(queryKey ?? [{ limit, offset, orderBy }]), +]; export type PoolServicePostPoolMutationResult = Awaited< ReturnType >; +export type VariableServicePostVariableMutationResult = Awaited< + ReturnType +>; export type DagServicePatchDagsMutationResult = Awaited< ReturnType >; export type DagServicePatchDagMutationResult = Awaited< ReturnType >; -export type VariableServicePatchVariableMutationResult = Awaited< - ReturnType ->; export type DagRunServicePatchDagRunStateMutationResult = Awaited< ReturnType >; export type PoolServicePatchPoolMutationResult = Awaited< ReturnType >; -export type DagServiceDeleteDagMutationResult = Awaited< - ReturnType +export type VariableServicePatchVariableMutationResult = Awaited< + ReturnType >; export type ConnectionServiceDeleteConnectionMutationResult = Awaited< ReturnType >; -export type VariableServiceDeleteVariableMutationResult = Awaited< - ReturnType +export type DagServiceDeleteDagMutationResult = Awaited< + ReturnType >; export type DagRunServiceDeleteDagRunMutationResult = Awaited< ReturnType @@ -462,3 +482,6 @@ export type DagRunServiceDeleteDagRunMutationResult = Awaited< export type PoolServiceDeletePoolMutationResult = Awaited< ReturnType >; +export type VariableServiceDeleteVariableMutationResult = Awaited< + ReturnType +>; diff --git a/airflow/ui/openapi-gen/queries/prefetch.ts b/airflow/ui/openapi-gen/queries/prefetch.ts index 350f9deddcf7..f1924acdbac8 100644 --- a/airflow/ui/openapi-gen/queries/prefetch.ts +++ b/airflow/ui/openapi-gen/queries/prefetch.ts @@ -6,6 +6,7 @@ import { ConnectionService, DagRunService, DagService, + DagSourceService, DagsService, DashboardService, EventLogService, @@ -134,6 +135,56 @@ export const prefetchUseDagsServiceRecentDagRuns = ( tags, }), }); +/** + * Get Connection + * Get a connection entry. + * @param data The data for the request. + * @param data.connectionId + * @returns ConnectionResponse Successful Response + * @throws ApiError + */ +export const prefetchUseConnectionServiceGetConnection = ( + queryClient: QueryClient, + { + connectionId, + }: { + connectionId: string; + }, +) => + queryClient.prefetchQuery({ + queryKey: Common.UseConnectionServiceGetConnectionKeyFn({ connectionId }), + queryFn: () => ConnectionService.getConnection({ connectionId }), + }); +/** + * Get Connections + * Get all connection entries. + * @param data The data for the request. + * @param data.limit + * @param data.offset + * @param data.orderBy + * @returns ConnectionCollectionResponse Successful Response + * @throws ApiError + */ +export const prefetchUseConnectionServiceGetConnections = ( + queryClient: QueryClient, + { + limit, + offset, + orderBy, + }: { + limit?: number; + offset?: number; + orderBy?: string; + } = {}, +) => + queryClient.prefetchQuery({ + queryKey: Common.UseConnectionServiceGetConnectionsKeyFn({ + limit, + offset, + orderBy, + }), + queryFn: () => ConnectionService.getConnections({ limit, offset, orderBy }), + }); /** * Get Dags * Get all DAGs. @@ -280,126 +331,52 @@ export const prefetchUseDagServiceGetDagDetails = ( queryFn: () => DagService.getDagDetails({ dagId }), }); /** - * Get Connection - * Get a connection entry. + * Get Dag Run * @param data The data for the request. - * @param data.connectionId - * @returns ConnectionResponse Successful Response + * @param data.dagId + * @param data.dagRunId + * @returns DAGRunResponse Successful Response * @throws ApiError */ -export const prefetchUseConnectionServiceGetConnection = ( +export const prefetchUseDagRunServiceGetDagRun = ( queryClient: QueryClient, { - connectionId, + dagId, + dagRunId, }: { - connectionId: string; + dagId: string; + dagRunId: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseConnectionServiceGetConnectionKeyFn({ connectionId }), - queryFn: () => ConnectionService.getConnection({ connectionId }), - }); -/** - * Get Connections - * Get all connection entries. - * @param data The data for the request. - * @param data.limit - * @param data.offset - * @param data.orderBy - * @returns ConnectionCollectionResponse Successful Response - * @throws ApiError - */ -export const prefetchUseConnectionServiceGetConnections = ( - queryClient: QueryClient, - { - limit, - offset, - orderBy, - }: { - limit?: number; - offset?: number; - orderBy?: string; - } = {}, -) => - queryClient.prefetchQuery({ - queryKey: Common.UseConnectionServiceGetConnectionsKeyFn({ - limit, - offset, - orderBy, - }), - queryFn: () => ConnectionService.getConnections({ limit, offset, orderBy }), + queryKey: Common.UseDagRunServiceGetDagRunKeyFn({ dagId, dagRunId }), + queryFn: () => DagRunService.getDagRun({ dagId, dagRunId }), }); /** - * Get Variable - * Get a variable entry. + * Get Dag Source + * Get source code using file token. * @param data The data for the request. - * @param data.variableKey - * @returns VariableResponse Successful Response + * @param data.fileToken + * @param data.accept + * @returns DAGSourceResponse Successful Response * @throws ApiError */ -export const prefetchUseVariableServiceGetVariable = ( +export const prefetchUseDagSourceServiceGetDagSource = ( queryClient: QueryClient, { - variableKey, + accept, + fileToken, }: { - variableKey: string; + accept?: string; + fileToken: string; }, ) => queryClient.prefetchQuery({ - queryKey: Common.UseVariableServiceGetVariableKeyFn({ variableKey }), - queryFn: () => VariableService.getVariable({ variableKey }), - }); -/** - * Get Variables - * Get all Variables entries. - * @param data The data for the request. - * @param data.limit - * @param data.offset - * @param data.orderBy - * @returns VariableCollectionResponse Successful Response - * @throws ApiError - */ -export const prefetchUseVariableServiceGetVariables = ( - queryClient: QueryClient, - { - limit, - offset, - orderBy, - }: { - limit?: number; - offset?: number; - orderBy?: string; - } = {}, -) => - queryClient.prefetchQuery({ - queryKey: Common.UseVariableServiceGetVariablesKeyFn({ - limit, - offset, - orderBy, + queryKey: Common.UseDagSourceServiceGetDagSourceKeyFn({ + accept, + fileToken, }), - queryFn: () => VariableService.getVariables({ limit, offset, orderBy }), - }); -/** - * Get Dag Run - * @param data The data for the request. - * @param data.dagId - * @param data.dagRunId - * @returns DAGRunResponse Successful Response - * @throws ApiError - */ -export const prefetchUseDagRunServiceGetDagRun = ( - queryClient: QueryClient, - { - dagId, - dagRunId, - }: { - dagId: string; - dagRunId: string; - }, -) => - queryClient.prefetchQuery({ - queryKey: Common.UseDagRunServiceGetDagRunKeyFn({ dagId, dagRunId }), - queryFn: () => DagRunService.getDagRun({ dagId, dagRunId }), + queryFn: () => DagSourceService.getDagSource({ accept, fileToken }), }); /** * Get Health @@ -532,3 +509,53 @@ export const prefetchUseEventLogServiceGetEventLog = ( queryKey: Common.UseEventLogServiceGetEventLogKeyFn({ eventLogId }), queryFn: () => EventLogService.getEventLog({ eventLogId }), }); +/** + * Get Variable + * Get a variable entry. + * @param data The data for the request. + * @param data.variableKey + * @returns VariableResponse Successful Response + * @throws ApiError + */ +export const prefetchUseVariableServiceGetVariable = ( + queryClient: QueryClient, + { + variableKey, + }: { + variableKey: string; + }, +) => + queryClient.prefetchQuery({ + queryKey: Common.UseVariableServiceGetVariableKeyFn({ variableKey }), + queryFn: () => VariableService.getVariable({ variableKey }), + }); +/** + * Get Variables + * Get all Variables entries. + * @param data The data for the request. + * @param data.limit + * @param data.offset + * @param data.orderBy + * @returns VariableCollectionResponse Successful Response + * @throws ApiError + */ +export const prefetchUseVariableServiceGetVariables = ( + queryClient: QueryClient, + { + limit, + offset, + orderBy, + }: { + limit?: number; + offset?: number; + orderBy?: string; + } = {}, +) => + queryClient.prefetchQuery({ + queryKey: Common.UseVariableServiceGetVariablesKeyFn({ + limit, + offset, + orderBy, + }), + queryFn: () => VariableService.getVariables({ limit, offset, orderBy }), + }); diff --git a/airflow/ui/openapi-gen/queries/queries.ts b/airflow/ui/openapi-gen/queries/queries.ts index a0d6a6585304..3b438c9e996c 100644 --- a/airflow/ui/openapi-gen/queries/queries.ts +++ b/airflow/ui/openapi-gen/queries/queries.ts @@ -11,6 +11,7 @@ import { ConnectionService, DagRunService, DagService, + DagSourceService, DagsService, DashboardService, EventLogService, @@ -168,6 +169,71 @@ export const useDagsServiceRecentDagRuns = < }) as TData, ...options, }); +/** + * Get Connection + * Get a connection entry. + * @param data The data for the request. + * @param data.connectionId + * @returns ConnectionResponse Successful Response + * @throws ApiError + */ +export const useConnectionServiceGetConnection = < + TData = Common.ConnectionServiceGetConnectionDefaultResponse, + TError = unknown, + TQueryKey extends Array = unknown[], +>( + { + connectionId, + }: { + connectionId: string; + }, + queryKey?: TQueryKey, + options?: Omit, "queryKey" | "queryFn">, +) => + useQuery({ + queryKey: Common.UseConnectionServiceGetConnectionKeyFn( + { connectionId }, + queryKey, + ), + queryFn: () => ConnectionService.getConnection({ connectionId }) as TData, + ...options, + }); +/** + * Get Connections + * Get all connection entries. + * @param data The data for the request. + * @param data.limit + * @param data.offset + * @param data.orderBy + * @returns ConnectionCollectionResponse Successful Response + * @throws ApiError + */ +export const useConnectionServiceGetConnections = < + TData = Common.ConnectionServiceGetConnectionsDefaultResponse, + TError = unknown, + TQueryKey extends Array = unknown[], +>( + { + limit, + offset, + orderBy, + }: { + limit?: number; + offset?: number; + orderBy?: string; + } = {}, + queryKey?: TQueryKey, + options?: Omit, "queryKey" | "queryFn">, +) => + useQuery({ + queryKey: Common.UseConnectionServiceGetConnectionsKeyFn( + { limit, offset, orderBy }, + queryKey, + ), + queryFn: () => + ConnectionService.getConnections({ limit, offset, orderBy }) as TData, + ...options, + }); /** * Get Dags * Get all DAGs. @@ -344,164 +410,67 @@ export const useDagServiceGetDagDetails = < ...options, }); /** - * Get Connection - * Get a connection entry. + * Get Dag Run * @param data The data for the request. - * @param data.connectionId - * @returns ConnectionResponse Successful Response + * @param data.dagId + * @param data.dagRunId + * @returns DAGRunResponse Successful Response * @throws ApiError */ -export const useConnectionServiceGetConnection = < - TData = Common.ConnectionServiceGetConnectionDefaultResponse, +export const useDagRunServiceGetDagRun = < + TData = Common.DagRunServiceGetDagRunDefaultResponse, TError = unknown, TQueryKey extends Array = unknown[], >( { - connectionId, + dagId, + dagRunId, }: { - connectionId: string; + dagId: string; + dagRunId: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseConnectionServiceGetConnectionKeyFn( - { connectionId }, - queryKey, - ), - queryFn: () => ConnectionService.getConnection({ connectionId }) as TData, - ...options, - }); -/** - * Get Connections - * Get all connection entries. - * @param data The data for the request. - * @param data.limit - * @param data.offset - * @param data.orderBy - * @returns ConnectionCollectionResponse Successful Response - * @throws ApiError - */ -export const useConnectionServiceGetConnections = < - TData = Common.ConnectionServiceGetConnectionsDefaultResponse, - TError = unknown, - TQueryKey extends Array = unknown[], ->( - { - limit, - offset, - orderBy, - }: { - limit?: number; - offset?: number; - orderBy?: string; - } = {}, - queryKey?: TQueryKey, - options?: Omit, "queryKey" | "queryFn">, -) => - useQuery({ - queryKey: Common.UseConnectionServiceGetConnectionsKeyFn( - { limit, offset, orderBy }, + queryKey: Common.UseDagRunServiceGetDagRunKeyFn( + { dagId, dagRunId }, queryKey, ), - queryFn: () => - ConnectionService.getConnections({ limit, offset, orderBy }) as TData, + queryFn: () => DagRunService.getDagRun({ dagId, dagRunId }) as TData, ...options, }); /** - * Get Variable - * Get a variable entry. + * Get Dag Source + * Get source code using file token. * @param data The data for the request. - * @param data.variableKey - * @returns VariableResponse Successful Response + * @param data.fileToken + * @param data.accept + * @returns DAGSourceResponse Successful Response * @throws ApiError */ -export const useVariableServiceGetVariable = < - TData = Common.VariableServiceGetVariableDefaultResponse, +export const useDagSourceServiceGetDagSource = < + TData = Common.DagSourceServiceGetDagSourceDefaultResponse, TError = unknown, TQueryKey extends Array = unknown[], >( { - variableKey, + accept, + fileToken, }: { - variableKey: string; + accept?: string; + fileToken: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useQuery({ - queryKey: Common.UseVariableServiceGetVariableKeyFn( - { variableKey }, - queryKey, - ), - queryFn: () => VariableService.getVariable({ variableKey }) as TData, - ...options, - }); -/** - * Get Variables - * Get all Variables entries. - * @param data The data for the request. - * @param data.limit - * @param data.offset - * @param data.orderBy - * @returns VariableCollectionResponse Successful Response - * @throws ApiError - */ -export const useVariableServiceGetVariables = < - TData = Common.VariableServiceGetVariablesDefaultResponse, - TError = unknown, - TQueryKey extends Array = unknown[], ->( - { - limit, - offset, - orderBy, - }: { - limit?: number; - offset?: number; - orderBy?: string; - } = {}, - queryKey?: TQueryKey, - options?: Omit, "queryKey" | "queryFn">, -) => - useQuery({ - queryKey: Common.UseVariableServiceGetVariablesKeyFn( - { limit, offset, orderBy }, + queryKey: Common.UseDagSourceServiceGetDagSourceKeyFn( + { accept, fileToken }, queryKey, ), queryFn: () => - VariableService.getVariables({ limit, offset, orderBy }) as TData, - ...options, - }); -/** - * Get Dag Run - * @param data The data for the request. - * @param data.dagId - * @param data.dagRunId - * @returns DAGRunResponse Successful Response - * @throws ApiError - */ -export const useDagRunServiceGetDagRun = < - TData = Common.DagRunServiceGetDagRunDefaultResponse, - TError = unknown, - TQueryKey extends Array = unknown[], ->( - { - dagId, - dagRunId, - }: { - dagId: string; - dagRunId: string; - }, - queryKey?: TQueryKey, - options?: Omit, "queryKey" | "queryFn">, -) => - useQuery({ - queryKey: Common.UseDagRunServiceGetDagRunKeyFn( - { dagId, dagRunId }, - queryKey, - ), - queryFn: () => DagRunService.getDagRun({ dagId, dagRunId }) as TData, + DagSourceService.getDagSource({ accept, fileToken }) as TData, ...options, }); /** @@ -694,15 +663,80 @@ export const useEventLogServiceGetEventLog = < ...options, }); /** - * Post Variable - * Create a variable. + * Get Variable + * Get a variable entry. * @param data The data for the request. - * @param data.requestBody + * @param data.variableKey * @returns VariableResponse Successful Response * @throws ApiError */ -export const useVariableServicePostVariable = < - TData = Common.VariableServicePostVariableMutationResult, +export const useVariableServiceGetVariable = < + TData = Common.VariableServiceGetVariableDefaultResponse, + TError = unknown, + TQueryKey extends Array = unknown[], +>( + { + variableKey, + }: { + variableKey: string; + }, + queryKey?: TQueryKey, + options?: Omit, "queryKey" | "queryFn">, +) => + useQuery({ + queryKey: Common.UseVariableServiceGetVariableKeyFn( + { variableKey }, + queryKey, + ), + queryFn: () => VariableService.getVariable({ variableKey }) as TData, + ...options, + }); +/** + * Get Variables + * Get all Variables entries. + * @param data The data for the request. + * @param data.limit + * @param data.offset + * @param data.orderBy + * @returns VariableCollectionResponse Successful Response + * @throws ApiError + */ +export const useVariableServiceGetVariables = < + TData = Common.VariableServiceGetVariablesDefaultResponse, + TError = unknown, + TQueryKey extends Array = unknown[], +>( + { + limit, + offset, + orderBy, + }: { + limit?: number; + offset?: number; + orderBy?: string; + } = {}, + queryKey?: TQueryKey, + options?: Omit, "queryKey" | "queryFn">, +) => + useQuery({ + queryKey: Common.UseVariableServiceGetVariablesKeyFn( + { limit, offset, orderBy }, + queryKey, + ), + queryFn: () => + VariableService.getVariables({ limit, offset, orderBy }) as TData, + ...options, + }); +/** + * Post Pool + * Create a Pool. + * @param data The data for the request. + * @param data.requestBody + * @returns PoolResponse Successful Response + * @throws ApiError + */ +export const usePoolServicePostPool = < + TData = Common.PoolServicePostPoolMutationResult, TError = unknown, TContext = unknown, >( @@ -711,7 +745,7 @@ export const useVariableServicePostVariable = < TData, TError, { - requestBody: VariableBody; + requestBody: PoolPostBody; }, TContext >, @@ -722,26 +756,24 @@ export const useVariableServicePostVariable = < TData, TError, { - requestBody: VariableBody; + requestBody: PoolPostBody; }, TContext >({ mutationFn: ({ requestBody }) => - VariableService.postVariable({ - requestBody, - }) as unknown as Promise, + PoolService.postPool({ requestBody }) as unknown as Promise, ...options, }); /** - * Post Pool - * Create a Pool. + * Post Variable + * Create a variable. * @param data The data for the request. * @param data.requestBody - * @returns PoolResponse Successful Response + * @returns VariableResponse Successful Response * @throws ApiError */ -export const usePoolServicePostPool = < - TData = Common.PoolServicePostPoolMutationResult, +export const useVariableServicePostVariable = < + TData = Common.VariableServicePostVariableMutationResult, TError = unknown, TContext = unknown, >( @@ -750,7 +782,7 @@ export const usePoolServicePostPool = < TData, TError, { - requestBody: PoolPostBody; + requestBody: VariableBody; }, TContext >, @@ -761,12 +793,14 @@ export const usePoolServicePostPool = < TData, TError, { - requestBody: PoolPostBody; + requestBody: VariableBody; }, TContext >({ mutationFn: ({ requestBody }) => - PoolService.postPool({ requestBody }) as unknown as Promise, + VariableService.postVariable({ + requestBody, + }) as unknown as Promise, ...options, }); /** @@ -902,53 +936,6 @@ export const useDagServicePatchDag = < }) as unknown as Promise, ...options, }); -/** - * Patch Variable - * Update a variable by key. - * @param data The data for the request. - * @param data.variableKey - * @param data.requestBody - * @param data.updateMask - * @returns VariableResponse Successful Response - * @throws ApiError - */ -export const useVariableServicePatchVariable = < - TData = Common.VariableServicePatchVariableMutationResult, - TError = unknown, - TContext = unknown, ->( - options?: Omit< - UseMutationOptions< - TData, - TError, - { - requestBody: VariableBody; - updateMask?: string[]; - variableKey: string; - }, - TContext - >, - "mutationFn" - >, -) => - useMutation< - TData, - TError, - { - requestBody: VariableBody; - updateMask?: string[]; - variableKey: string; - }, - TContext - >({ - mutationFn: ({ requestBody, updateMask, variableKey }) => - VariableService.patchVariable({ - requestBody, - updateMask, - variableKey, - }) as unknown as Promise, - ...options, - }); /** * Patch Dag Run State * Modify a DAG Run. @@ -1048,15 +1035,17 @@ export const usePoolServicePatchPool = < ...options, }); /** - * Delete Dag - * Delete the specific DAG. + * Patch Variable + * Update a variable by key. * @param data The data for the request. - * @param data.dagId - * @returns unknown Successful Response + * @param data.variableKey + * @param data.requestBody + * @param data.updateMask + * @returns VariableResponse Successful Response * @throws ApiError */ -export const useDagServiceDeleteDag = < - TData = Common.DagServiceDeleteDagMutationResult, +export const useVariableServicePatchVariable = < + TData = Common.VariableServicePatchVariableMutationResult, TError = unknown, TContext = unknown, >( @@ -1065,7 +1054,9 @@ export const useDagServiceDeleteDag = < TData, TError, { - dagId: string; + requestBody: VariableBody; + updateMask?: string[]; + variableKey: string; }, TContext >, @@ -1076,12 +1067,18 @@ export const useDagServiceDeleteDag = < TData, TError, { - dagId: string; + requestBody: VariableBody; + updateMask?: string[]; + variableKey: string; }, TContext >({ - mutationFn: ({ dagId }) => - DagService.deleteDag({ dagId }) as unknown as Promise, + mutationFn: ({ requestBody, updateMask, variableKey }) => + VariableService.patchVariable({ + requestBody, + updateMask, + variableKey, + }) as unknown as Promise, ...options, }); /** @@ -1124,15 +1121,15 @@ export const useConnectionServiceDeleteConnection = < ...options, }); /** - * Delete Variable - * Delete a variable entry. + * Delete Dag + * Delete the specific DAG. * @param data The data for the request. - * @param data.variableKey - * @returns void Successful Response + * @param data.dagId + * @returns unknown Successful Response * @throws ApiError */ -export const useVariableServiceDeleteVariable = < - TData = Common.VariableServiceDeleteVariableMutationResult, +export const useDagServiceDeleteDag = < + TData = Common.DagServiceDeleteDagMutationResult, TError = unknown, TContext = unknown, >( @@ -1141,7 +1138,7 @@ export const useVariableServiceDeleteVariable = < TData, TError, { - variableKey: string; + dagId: string; }, TContext >, @@ -1152,14 +1149,12 @@ export const useVariableServiceDeleteVariable = < TData, TError, { - variableKey: string; + dagId: string; }, TContext >({ - mutationFn: ({ variableKey }) => - VariableService.deleteVariable({ - variableKey, - }) as unknown as Promise, + mutationFn: ({ dagId }) => + DagService.deleteDag({ dagId }) as unknown as Promise, ...options, }); /** @@ -1242,3 +1237,42 @@ export const usePoolServiceDeletePool = < PoolService.deletePool({ poolName }) as unknown as Promise, ...options, }); +/** + * Delete Variable + * Delete a variable entry. + * @param data The data for the request. + * @param data.variableKey + * @returns void Successful Response + * @throws ApiError + */ +export const useVariableServiceDeleteVariable = < + TData = Common.VariableServiceDeleteVariableMutationResult, + TError = unknown, + TContext = unknown, +>( + options?: Omit< + UseMutationOptions< + TData, + TError, + { + variableKey: string; + }, + TContext + >, + "mutationFn" + >, +) => + useMutation< + TData, + TError, + { + variableKey: string; + }, + TContext + >({ + mutationFn: ({ variableKey }) => + VariableService.deleteVariable({ + variableKey, + }) as unknown as Promise, + ...options, + }); diff --git a/airflow/ui/openapi-gen/queries/suspense.ts b/airflow/ui/openapi-gen/queries/suspense.ts index 16f8ca003038..9af6582f88d8 100644 --- a/airflow/ui/openapi-gen/queries/suspense.ts +++ b/airflow/ui/openapi-gen/queries/suspense.ts @@ -6,6 +6,7 @@ import { ConnectionService, DagRunService, DagService, + DagSourceService, DagsService, DashboardService, EventLogService, @@ -156,6 +157,71 @@ export const useDagsServiceRecentDagRunsSuspense = < }) as TData, ...options, }); +/** + * Get Connection + * Get a connection entry. + * @param data The data for the request. + * @param data.connectionId + * @returns ConnectionResponse Successful Response + * @throws ApiError + */ +export const useConnectionServiceGetConnectionSuspense = < + TData = Common.ConnectionServiceGetConnectionDefaultResponse, + TError = unknown, + TQueryKey extends Array = unknown[], +>( + { + connectionId, + }: { + connectionId: string; + }, + queryKey?: TQueryKey, + options?: Omit, "queryKey" | "queryFn">, +) => + useSuspenseQuery({ + queryKey: Common.UseConnectionServiceGetConnectionKeyFn( + { connectionId }, + queryKey, + ), + queryFn: () => ConnectionService.getConnection({ connectionId }) as TData, + ...options, + }); +/** + * Get Connections + * Get all connection entries. + * @param data The data for the request. + * @param data.limit + * @param data.offset + * @param data.orderBy + * @returns ConnectionCollectionResponse Successful Response + * @throws ApiError + */ +export const useConnectionServiceGetConnectionsSuspense = < + TData = Common.ConnectionServiceGetConnectionsDefaultResponse, + TError = unknown, + TQueryKey extends Array = unknown[], +>( + { + limit, + offset, + orderBy, + }: { + limit?: number; + offset?: number; + orderBy?: string; + } = {}, + queryKey?: TQueryKey, + options?: Omit, "queryKey" | "queryFn">, +) => + useSuspenseQuery({ + queryKey: Common.UseConnectionServiceGetConnectionsKeyFn( + { limit, offset, orderBy }, + queryKey, + ), + queryFn: () => + ConnectionService.getConnections({ limit, offset, orderBy }) as TData, + ...options, + }); /** * Get Dags * Get all DAGs. @@ -332,164 +398,67 @@ export const useDagServiceGetDagDetailsSuspense = < ...options, }); /** - * Get Connection - * Get a connection entry. + * Get Dag Run * @param data The data for the request. - * @param data.connectionId - * @returns ConnectionResponse Successful Response + * @param data.dagId + * @param data.dagRunId + * @returns DAGRunResponse Successful Response * @throws ApiError */ -export const useConnectionServiceGetConnectionSuspense = < - TData = Common.ConnectionServiceGetConnectionDefaultResponse, +export const useDagRunServiceGetDagRunSuspense = < + TData = Common.DagRunServiceGetDagRunDefaultResponse, TError = unknown, TQueryKey extends Array = unknown[], >( { - connectionId, + dagId, + dagRunId, }: { - connectionId: string; + dagId: string; + dagRunId: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseConnectionServiceGetConnectionKeyFn( - { connectionId }, - queryKey, - ), - queryFn: () => ConnectionService.getConnection({ connectionId }) as TData, - ...options, - }); -/** - * Get Connections - * Get all connection entries. - * @param data The data for the request. - * @param data.limit - * @param data.offset - * @param data.orderBy - * @returns ConnectionCollectionResponse Successful Response - * @throws ApiError - */ -export const useConnectionServiceGetConnectionsSuspense = < - TData = Common.ConnectionServiceGetConnectionsDefaultResponse, - TError = unknown, - TQueryKey extends Array = unknown[], ->( - { - limit, - offset, - orderBy, - }: { - limit?: number; - offset?: number; - orderBy?: string; - } = {}, - queryKey?: TQueryKey, - options?: Omit, "queryKey" | "queryFn">, -) => - useSuspenseQuery({ - queryKey: Common.UseConnectionServiceGetConnectionsKeyFn( - { limit, offset, orderBy }, + queryKey: Common.UseDagRunServiceGetDagRunKeyFn( + { dagId, dagRunId }, queryKey, ), - queryFn: () => - ConnectionService.getConnections({ limit, offset, orderBy }) as TData, + queryFn: () => DagRunService.getDagRun({ dagId, dagRunId }) as TData, ...options, }); /** - * Get Variable - * Get a variable entry. + * Get Dag Source + * Get source code using file token. * @param data The data for the request. - * @param data.variableKey - * @returns VariableResponse Successful Response + * @param data.fileToken + * @param data.accept + * @returns DAGSourceResponse Successful Response * @throws ApiError */ -export const useVariableServiceGetVariableSuspense = < - TData = Common.VariableServiceGetVariableDefaultResponse, +export const useDagSourceServiceGetDagSourceSuspense = < + TData = Common.DagSourceServiceGetDagSourceDefaultResponse, TError = unknown, TQueryKey extends Array = unknown[], >( { - variableKey, + accept, + fileToken, }: { - variableKey: string; + accept?: string; + fileToken: string; }, queryKey?: TQueryKey, options?: Omit, "queryKey" | "queryFn">, ) => useSuspenseQuery({ - queryKey: Common.UseVariableServiceGetVariableKeyFn( - { variableKey }, - queryKey, - ), - queryFn: () => VariableService.getVariable({ variableKey }) as TData, - ...options, - }); -/** - * Get Variables - * Get all Variables entries. - * @param data The data for the request. - * @param data.limit - * @param data.offset - * @param data.orderBy - * @returns VariableCollectionResponse Successful Response - * @throws ApiError - */ -export const useVariableServiceGetVariablesSuspense = < - TData = Common.VariableServiceGetVariablesDefaultResponse, - TError = unknown, - TQueryKey extends Array = unknown[], ->( - { - limit, - offset, - orderBy, - }: { - limit?: number; - offset?: number; - orderBy?: string; - } = {}, - queryKey?: TQueryKey, - options?: Omit, "queryKey" | "queryFn">, -) => - useSuspenseQuery({ - queryKey: Common.UseVariableServiceGetVariablesKeyFn( - { limit, offset, orderBy }, + queryKey: Common.UseDagSourceServiceGetDagSourceKeyFn( + { accept, fileToken }, queryKey, ), queryFn: () => - VariableService.getVariables({ limit, offset, orderBy }) as TData, - ...options, - }); -/** - * Get Dag Run - * @param data The data for the request. - * @param data.dagId - * @param data.dagRunId - * @returns DAGRunResponse Successful Response - * @throws ApiError - */ -export const useDagRunServiceGetDagRunSuspense = < - TData = Common.DagRunServiceGetDagRunDefaultResponse, - TError = unknown, - TQueryKey extends Array = unknown[], ->( - { - dagId, - dagRunId, - }: { - dagId: string; - dagRunId: string; - }, - queryKey?: TQueryKey, - options?: Omit, "queryKey" | "queryFn">, -) => - useSuspenseQuery({ - queryKey: Common.UseDagRunServiceGetDagRunKeyFn( - { dagId, dagRunId }, - queryKey, - ), - queryFn: () => DagRunService.getDagRun({ dagId, dagRunId }) as TData, + DagSourceService.getDagSource({ accept, fileToken }) as TData, ...options, }); /** @@ -681,3 +650,68 @@ export const useEventLogServiceGetEventLogSuspense = < queryFn: () => EventLogService.getEventLog({ eventLogId }) as TData, ...options, }); +/** + * Get Variable + * Get a variable entry. + * @param data The data for the request. + * @param data.variableKey + * @returns VariableResponse Successful Response + * @throws ApiError + */ +export const useVariableServiceGetVariableSuspense = < + TData = Common.VariableServiceGetVariableDefaultResponse, + TError = unknown, + TQueryKey extends Array = unknown[], +>( + { + variableKey, + }: { + variableKey: string; + }, + queryKey?: TQueryKey, + options?: Omit, "queryKey" | "queryFn">, +) => + useSuspenseQuery({ + queryKey: Common.UseVariableServiceGetVariableKeyFn( + { variableKey }, + queryKey, + ), + queryFn: () => VariableService.getVariable({ variableKey }) as TData, + ...options, + }); +/** + * Get Variables + * Get all Variables entries. + * @param data The data for the request. + * @param data.limit + * @param data.offset + * @param data.orderBy + * @returns VariableCollectionResponse Successful Response + * @throws ApiError + */ +export const useVariableServiceGetVariablesSuspense = < + TData = Common.VariableServiceGetVariablesDefaultResponse, + TError = unknown, + TQueryKey extends Array = unknown[], +>( + { + limit, + offset, + orderBy, + }: { + limit?: number; + offset?: number; + orderBy?: string; + } = {}, + queryKey?: TQueryKey, + options?: Omit, "queryKey" | "queryFn">, +) => + useSuspenseQuery({ + queryKey: Common.UseVariableServiceGetVariablesKeyFn( + { limit, offset, orderBy }, + queryKey, + ), + queryFn: () => + VariableService.getVariables({ limit, offset, orderBy }) as TData, + ...options, + }); diff --git a/airflow/ui/openapi-gen/requests/schemas.gen.ts b/airflow/ui/openapi-gen/requests/schemas.gen.ts index 3982407c5f18..a991cce370bd 100644 --- a/airflow/ui/openapi-gen/requests/schemas.gen.ts +++ b/airflow/ui/openapi-gen/requests/schemas.gen.ts @@ -1095,6 +1095,26 @@ export const $DAGRunTypes = { description: "DAG Run Types for responses.", } as const; +export const $DAGSourceResponse = { + properties: { + content: { + anyOf: [ + { + type: "string", + }, + { + type: "null", + }, + ], + title: "Content", + }, + }, + type: "object", + required: ["content"], + title: "DAGSourceResponse", + description: "DAG Source serializer for responses.", +} as const; + export const $DAGTagCollectionResponse = { properties: { tags: { diff --git a/airflow/ui/openapi-gen/requests/services.gen.ts b/airflow/ui/openapi-gen/requests/services.gen.ts index 56207631d154..36c4fa46d794 100644 --- a/airflow/ui/openapi-gen/requests/services.gen.ts +++ b/airflow/ui/openapi-gen/requests/services.gen.ts @@ -9,6 +9,12 @@ import type { HistoricalMetricsResponse, RecentDagRunsData, RecentDagRunsResponse, + DeleteConnectionData, + DeleteConnectionResponse, + GetConnectionData, + GetConnectionResponse, + GetConnectionsData, + GetConnectionsResponse, GetDagsData, GetDagsResponse, PatchDagsData, @@ -23,28 +29,14 @@ import type { DeleteDagResponse, GetDagDetailsData, GetDagDetailsResponse, - DeleteConnectionData, - DeleteConnectionResponse, - GetConnectionData, - GetConnectionResponse, - GetConnectionsData, - GetConnectionsResponse, - DeleteVariableData, - DeleteVariableResponse, - GetVariableData, - GetVariableResponse, - PatchVariableData, - PatchVariableResponse, - GetVariablesData, - GetVariablesResponse, - PostVariableData, - PostVariableResponse, GetDagRunData, GetDagRunResponse, DeleteDagRunData, DeleteDagRunResponse, PatchDagRunStateData, PatchDagRunStateResponse, + GetDagSourceData, + GetDagSourceResponse, GetHealthResponse, DeletePoolData, DeletePoolResponse, @@ -63,6 +55,16 @@ import type { GetVersionResponse, GetEventLogData, GetEventLogResponse, + DeleteVariableData, + DeleteVariableResponse, + GetVariableData, + GetVariableResponse, + PatchVariableData, + PatchVariableResponse, + GetVariablesData, + GetVariablesResponse, + PostVariableData, + PostVariableResponse, } from "./types.gen"; export class AssetService { @@ -160,6 +162,90 @@ export class DagsService { } } +export class ConnectionService { + /** + * Delete Connection + * Delete a connection entry. + * @param data The data for the request. + * @param data.connectionId + * @returns void Successful Response + * @throws ApiError + */ + public static deleteConnection( + data: DeleteConnectionData, + ): CancelablePromise { + return __request(OpenAPI, { + method: "DELETE", + url: "/public/connections/{connection_id}", + path: { + connection_id: data.connectionId, + }, + errors: { + 401: "Unauthorized", + 403: "Forbidden", + 404: "Not Found", + 422: "Validation Error", + }, + }); + } + + /** + * Get Connection + * Get a connection entry. + * @param data The data for the request. + * @param data.connectionId + * @returns ConnectionResponse Successful Response + * @throws ApiError + */ + public static getConnection( + data: GetConnectionData, + ): CancelablePromise { + return __request(OpenAPI, { + method: "GET", + url: "/public/connections/{connection_id}", + path: { + connection_id: data.connectionId, + }, + errors: { + 401: "Unauthorized", + 403: "Forbidden", + 404: "Not Found", + 422: "Validation Error", + }, + }); + } + + /** + * Get Connections + * Get all connection entries. + * @param data The data for the request. + * @param data.limit + * @param data.offset + * @param data.orderBy + * @returns ConnectionCollectionResponse Successful Response + * @throws ApiError + */ + public static getConnections( + data: GetConnectionsData = {}, + ): CancelablePromise { + return __request(OpenAPI, { + method: "GET", + url: "/public/connections/", + query: { + limit: data.limit, + offset: data.offset, + order_by: data.orderBy, + }, + errors: { + 401: "Unauthorized", + 403: "Forbidden", + 404: "Not Found", + 422: "Validation Error", + }, + }); + } +} + export class DagService { /** * Get Dags @@ -393,231 +479,6 @@ export class DagService { } } -export class ConnectionService { - /** - * Delete Connection - * Delete a connection entry. - * @param data The data for the request. - * @param data.connectionId - * @returns void Successful Response - * @throws ApiError - */ - public static deleteConnection( - data: DeleteConnectionData, - ): CancelablePromise { - return __request(OpenAPI, { - method: "DELETE", - url: "/public/connections/{connection_id}", - path: { - connection_id: data.connectionId, - }, - errors: { - 401: "Unauthorized", - 403: "Forbidden", - 404: "Not Found", - 422: "Validation Error", - }, - }); - } - - /** - * Get Connection - * Get a connection entry. - * @param data The data for the request. - * @param data.connectionId - * @returns ConnectionResponse Successful Response - * @throws ApiError - */ - public static getConnection( - data: GetConnectionData, - ): CancelablePromise { - return __request(OpenAPI, { - method: "GET", - url: "/public/connections/{connection_id}", - path: { - connection_id: data.connectionId, - }, - errors: { - 401: "Unauthorized", - 403: "Forbidden", - 404: "Not Found", - 422: "Validation Error", - }, - }); - } - - /** - * Get Connections - * Get all connection entries. - * @param data The data for the request. - * @param data.limit - * @param data.offset - * @param data.orderBy - * @returns ConnectionCollectionResponse Successful Response - * @throws ApiError - */ - public static getConnections( - data: GetConnectionsData = {}, - ): CancelablePromise { - return __request(OpenAPI, { - method: "GET", - url: "/public/connections/", - query: { - limit: data.limit, - offset: data.offset, - order_by: data.orderBy, - }, - errors: { - 401: "Unauthorized", - 403: "Forbidden", - 404: "Not Found", - 422: "Validation Error", - }, - }); - } -} - -export class VariableService { - /** - * Delete Variable - * Delete a variable entry. - * @param data The data for the request. - * @param data.variableKey - * @returns void Successful Response - * @throws ApiError - */ - public static deleteVariable( - data: DeleteVariableData, - ): CancelablePromise { - return __request(OpenAPI, { - method: "DELETE", - url: "/public/variables/{variable_key}", - path: { - variable_key: data.variableKey, - }, - errors: { - 401: "Unauthorized", - 403: "Forbidden", - 404: "Not Found", - 422: "Validation Error", - }, - }); - } - - /** - * Get Variable - * Get a variable entry. - * @param data The data for the request. - * @param data.variableKey - * @returns VariableResponse Successful Response - * @throws ApiError - */ - public static getVariable( - data: GetVariableData, - ): CancelablePromise { - return __request(OpenAPI, { - method: "GET", - url: "/public/variables/{variable_key}", - path: { - variable_key: data.variableKey, - }, - errors: { - 401: "Unauthorized", - 403: "Forbidden", - 404: "Not Found", - 422: "Validation Error", - }, - }); - } - - /** - * Patch Variable - * Update a variable by key. - * @param data The data for the request. - * @param data.variableKey - * @param data.requestBody - * @param data.updateMask - * @returns VariableResponse Successful Response - * @throws ApiError - */ - public static patchVariable( - data: PatchVariableData, - ): CancelablePromise { - return __request(OpenAPI, { - method: "PATCH", - url: "/public/variables/{variable_key}", - path: { - variable_key: data.variableKey, - }, - query: { - update_mask: data.updateMask, - }, - body: data.requestBody, - mediaType: "application/json", - errors: { - 400: "Bad Request", - 401: "Unauthorized", - 403: "Forbidden", - 404: "Not Found", - 422: "Validation Error", - }, - }); - } - - /** - * Get Variables - * Get all Variables entries. - * @param data The data for the request. - * @param data.limit - * @param data.offset - * @param data.orderBy - * @returns VariableCollectionResponse Successful Response - * @throws ApiError - */ - public static getVariables( - data: GetVariablesData = {}, - ): CancelablePromise { - return __request(OpenAPI, { - method: "GET", - url: "/public/variables/", - query: { - limit: data.limit, - offset: data.offset, - order_by: data.orderBy, - }, - errors: { - 401: "Unauthorized", - 403: "Forbidden", - 422: "Validation Error", - }, - }); - } - - /** - * Post Variable - * Create a variable. - * @param data The data for the request. - * @param data.requestBody - * @returns VariableResponse Successful Response - * @throws ApiError - */ - public static postVariable( - data: PostVariableData, - ): CancelablePromise { - return __request(OpenAPI, { - method: "POST", - url: "/public/variables/", - body: data.requestBody, - mediaType: "application/json", - errors: { - 401: "Unauthorized", - 403: "Forbidden", - 422: "Validation Error", - }, - }); - } -} - export class DagRunService { /** * Get Dag Run @@ -712,6 +573,40 @@ export class DagRunService { } } +export class DagSourceService { + /** + * Get Dag Source + * Get source code using file token. + * @param data The data for the request. + * @param data.fileToken + * @param data.accept + * @returns DAGSourceResponse Successful Response + * @throws ApiError + */ + public static getDagSource( + data: GetDagSourceData, + ): CancelablePromise { + return __request(OpenAPI, { + method: "GET", + url: "/public/dagSources/{file_token}", + path: { + file_token: data.fileToken, + }, + headers: { + accept: data.accept, + }, + errors: { + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "Not Found", + 406: "Not Acceptable", + 422: "Validation Error", + }, + }); + } +} + export class MonitorService { /** * Get Health @@ -961,3 +856,144 @@ export class EventLogService { }); } } + +export class VariableService { + /** + * Delete Variable + * Delete a variable entry. + * @param data The data for the request. + * @param data.variableKey + * @returns void Successful Response + * @throws ApiError + */ + public static deleteVariable( + data: DeleteVariableData, + ): CancelablePromise { + return __request(OpenAPI, { + method: "DELETE", + url: "/public/variables/{variable_key}", + path: { + variable_key: data.variableKey, + }, + errors: { + 401: "Unauthorized", + 403: "Forbidden", + 404: "Not Found", + 422: "Validation Error", + }, + }); + } + + /** + * Get Variable + * Get a variable entry. + * @param data The data for the request. + * @param data.variableKey + * @returns VariableResponse Successful Response + * @throws ApiError + */ + public static getVariable( + data: GetVariableData, + ): CancelablePromise { + return __request(OpenAPI, { + method: "GET", + url: "/public/variables/{variable_key}", + path: { + variable_key: data.variableKey, + }, + errors: { + 401: "Unauthorized", + 403: "Forbidden", + 404: "Not Found", + 422: "Validation Error", + }, + }); + } + + /** + * Patch Variable + * Update a variable by key. + * @param data The data for the request. + * @param data.variableKey + * @param data.requestBody + * @param data.updateMask + * @returns VariableResponse Successful Response + * @throws ApiError + */ + public static patchVariable( + data: PatchVariableData, + ): CancelablePromise { + return __request(OpenAPI, { + method: "PATCH", + url: "/public/variables/{variable_key}", + path: { + variable_key: data.variableKey, + }, + query: { + update_mask: data.updateMask, + }, + body: data.requestBody, + mediaType: "application/json", + errors: { + 400: "Bad Request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "Not Found", + 422: "Validation Error", + }, + }); + } + + /** + * Get Variables + * Get all Variables entries. + * @param data The data for the request. + * @param data.limit + * @param data.offset + * @param data.orderBy + * @returns VariableCollectionResponse Successful Response + * @throws ApiError + */ + public static getVariables( + data: GetVariablesData = {}, + ): CancelablePromise { + return __request(OpenAPI, { + method: "GET", + url: "/public/variables/", + query: { + limit: data.limit, + offset: data.offset, + order_by: data.orderBy, + }, + errors: { + 401: "Unauthorized", + 403: "Forbidden", + 422: "Validation Error", + }, + }); + } + + /** + * Post Variable + * Create a variable. + * @param data The data for the request. + * @param data.requestBody + * @returns VariableResponse Successful Response + * @throws ApiError + */ + public static postVariable( + data: PostVariableData, + ): CancelablePromise { + return __request(OpenAPI, { + method: "POST", + url: "/public/variables/", + body: data.requestBody, + mediaType: "application/json", + errors: { + 401: "Unauthorized", + 403: "Forbidden", + 422: "Validation Error", + }, + }); + } +} diff --git a/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow/ui/openapi-gen/requests/types.gen.ts index a3b1d8e6bef6..d375978b91f1 100644 --- a/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow/ui/openapi-gen/requests/types.gen.ts @@ -208,6 +208,13 @@ export type DAGRunTypes = { asset_triggered: number; }; +/** + * DAG Source serializer for responses. + */ +export type DAGSourceResponse = { + content: string | null; +}; + /** * DAG Tags Collection serializer for responses. */ @@ -559,6 +566,26 @@ export type RecentDagRunsData = { export type RecentDagRunsResponse = DAGWithLatestDagRunsCollectionResponse; +export type DeleteConnectionData = { + connectionId: string; +}; + +export type DeleteConnectionResponse = void; + +export type GetConnectionData = { + connectionId: string; +}; + +export type GetConnectionResponse = ConnectionResponse; + +export type GetConnectionsData = { + limit?: number; + offset?: number; + orderBy?: string; +}; + +export type GetConnectionsResponse = ConnectionCollectionResponse; + export type GetDagsData = { dagDisplayNamePattern?: string | null; dagIdPattern?: string | null; @@ -624,60 +651,6 @@ export type GetDagDetailsData = { export type GetDagDetailsResponse = DAGDetailsResponse; -export type DeleteConnectionData = { - connectionId: string; -}; - -export type DeleteConnectionResponse = void; - -export type GetConnectionData = { - connectionId: string; -}; - -export type GetConnectionResponse = ConnectionResponse; - -export type GetConnectionsData = { - limit?: number; - offset?: number; - orderBy?: string; -}; - -export type GetConnectionsResponse = ConnectionCollectionResponse; - -export type DeleteVariableData = { - variableKey: string; -}; - -export type DeleteVariableResponse = void; - -export type GetVariableData = { - variableKey: string; -}; - -export type GetVariableResponse = VariableResponse; - -export type PatchVariableData = { - requestBody: VariableBody; - updateMask?: Array | null; - variableKey: string; -}; - -export type PatchVariableResponse = VariableResponse; - -export type GetVariablesData = { - limit?: number; - offset?: number; - orderBy?: string; -}; - -export type GetVariablesResponse = VariableCollectionResponse; - -export type PostVariableData = { - requestBody: VariableBody; -}; - -export type PostVariableResponse = VariableResponse; - export type GetDagRunData = { dagId: string; dagRunId: string; @@ -701,6 +674,13 @@ export type PatchDagRunStateData = { export type PatchDagRunStateResponse = DAGRunResponse; +export type GetDagSourceData = { + accept?: string; + fileToken: string; +}; + +export type GetDagSourceResponse = DAGSourceResponse; + export type GetHealthResponse = HealthInfoSchema; export type DeletePoolData = { @@ -759,6 +739,40 @@ export type GetEventLogData = { export type GetEventLogResponse = EventLogResponse; +export type DeleteVariableData = { + variableKey: string; +}; + +export type DeleteVariableResponse = void; + +export type GetVariableData = { + variableKey: string; +}; + +export type GetVariableResponse = VariableResponse; + +export type PatchVariableData = { + requestBody: VariableBody; + updateMask?: Array | null; + variableKey: string; +}; + +export type PatchVariableResponse = VariableResponse; + +export type GetVariablesData = { + limit?: number; + offset?: number; + orderBy?: string; +}; + +export type GetVariablesResponse = VariableCollectionResponse; + +export type PostVariableData = { + requestBody: VariableBody; +}; + +export type PostVariableResponse = VariableResponse; + export type $OpenApiTs = { "/ui/next_run_assets/{dag_id}": { get: { @@ -811,6 +825,85 @@ export type $OpenApiTs = { }; }; }; + "/public/connections/{connection_id}": { + delete: { + req: DeleteConnectionData; + res: { + /** + * Successful Response + */ + 204: void; + /** + * Unauthorized + */ + 401: HTTPExceptionResponse; + /** + * Forbidden + */ + 403: HTTPExceptionResponse; + /** + * Not Found + */ + 404: HTTPExceptionResponse; + /** + * Validation Error + */ + 422: HTTPValidationError; + }; + }; + get: { + req: GetConnectionData; + res: { + /** + * Successful Response + */ + 200: ConnectionResponse; + /** + * Unauthorized + */ + 401: HTTPExceptionResponse; + /** + * Forbidden + */ + 403: HTTPExceptionResponse; + /** + * Not Found + */ + 404: HTTPExceptionResponse; + /** + * Validation Error + */ + 422: HTTPValidationError; + }; + }; + }; + "/public/connections/": { + get: { + req: GetConnectionsData; + res: { + /** + * Successful Response + */ + 200: ConnectionCollectionResponse; + /** + * Unauthorized + */ + 401: HTTPExceptionResponse; + /** + * Forbidden + */ + 403: HTTPExceptionResponse; + /** + * Not Found + */ + 404: HTTPExceptionResponse; + /** + * Validation Error + */ + 422: HTTPValidationError; + }; + }; + }; "/public/dags/": { get: { req: GetDagsData; @@ -998,14 +1091,14 @@ export type $OpenApiTs = { }; }; }; - "/public/connections/{connection_id}": { - delete: { - req: DeleteConnectionData; + "/public/dags/{dag_id}/dagRuns/{dag_run_id}": { + get: { + req: GetDagRunData; res: { /** * Successful Response */ - 204: void; + 200: DAGRunResponse; /** * Unauthorized */ @@ -1024,13 +1117,17 @@ export type $OpenApiTs = { 422: HTTPValidationError; }; }; - get: { - req: GetConnectionData; + delete: { + req: DeleteDagRunData; res: { /** * Successful Response */ - 200: ConnectionResponse; + 204: void; + /** + * Bad Request + */ + 400: HTTPExceptionResponse; /** * Unauthorized */ @@ -1049,15 +1146,17 @@ export type $OpenApiTs = { 422: HTTPValidationError; }; }; - }; - "/public/connections/": { - get: { - req: GetConnectionsData; + patch: { + req: PatchDagRunStateData; res: { /** * Successful Response */ - 200: ConnectionCollectionResponse; + 200: DAGRunResponse; + /** + * Bad Request + */ + 400: HTTPExceptionResponse; /** * Unauthorized */ @@ -1077,14 +1176,18 @@ export type $OpenApiTs = { }; }; }; - "/public/variables/{variable_key}": { - delete: { - req: DeleteVariableData; + "/public/dagSources/{file_token}": { + get: { + req: GetDagSourceData; res: { /** * Successful Response */ - 204: void; + 200: DAGSourceResponse; + /** + * Bad Request + */ + 400: HTTPExceptionResponse; /** * Unauthorized */ @@ -1097,44 +1200,35 @@ export type $OpenApiTs = { * Not Found */ 404: HTTPExceptionResponse; + /** + * Not Acceptable + */ + 406: HTTPExceptionResponse; /** * Validation Error */ 422: HTTPValidationError; }; }; + }; + "/public/monitor/health": { get: { - req: GetVariableData; res: { /** * Successful Response */ - 200: VariableResponse; - /** - * Unauthorized - */ - 401: HTTPExceptionResponse; - /** - * Forbidden - */ - 403: HTTPExceptionResponse; - /** - * Not Found - */ - 404: HTTPExceptionResponse; - /** - * Validation Error - */ - 422: HTTPValidationError; + 200: HealthInfoSchema; }; }; - patch: { - req: PatchVariableData; + }; + "/public/pools/{pool_name}": { + delete: { + req: DeletePoolData; res: { /** * Successful Response */ - 200: VariableResponse; + 204: void; /** * Bad Request */ @@ -1157,15 +1251,13 @@ export type $OpenApiTs = { 422: HTTPValidationError; }; }; - }; - "/public/variables/": { get: { - req: GetVariablesData; + req: GetPoolData; res: { /** * Successful Response */ - 200: VariableCollectionResponse; + 200: PoolResponse; /** * Unauthorized */ @@ -1174,19 +1266,27 @@ export type $OpenApiTs = { * Forbidden */ 403: HTTPExceptionResponse; + /** + * Not Found + */ + 404: HTTPExceptionResponse; /** * Validation Error */ 422: HTTPValidationError; }; }; - post: { - req: PostVariableData; + patch: { + req: PatchPoolData; res: { /** * Successful Response */ - 201: VariableResponse; + 200: PoolResponse; + /** + * Bad Request + */ + 400: HTTPExceptionResponse; /** * Unauthorized */ @@ -1195,6 +1295,10 @@ export type $OpenApiTs = { * Forbidden */ 403: HTTPExceptionResponse; + /** + * Not Found + */ + 404: HTTPExceptionResponse; /** * Validation Error */ @@ -1202,14 +1306,14 @@ export type $OpenApiTs = { }; }; }; - "/public/dags/{dag_id}/dagRuns/{dag_run_id}": { + "/public/pools/": { get: { - req: GetDagRunData; + req: GetPoolsData; res: { /** * Successful Response */ - 200: DAGRunResponse; + 200: PoolCollectionResponse; /** * Unauthorized */ @@ -1228,17 +1332,13 @@ export type $OpenApiTs = { 422: HTTPValidationError; }; }; - delete: { - req: DeleteDagRunData; + post: { + req: PostPoolData; res: { /** * Successful Response */ - 204: void; - /** - * Bad Request - */ - 400: HTTPExceptionResponse; + 201: PoolResponse; /** * Unauthorized */ @@ -1247,39 +1347,36 @@ export type $OpenApiTs = { * Forbidden */ 403: HTTPExceptionResponse; - /** - * Not Found - */ - 404: HTTPExceptionResponse; /** * Validation Error */ 422: HTTPValidationError; }; }; - patch: { - req: PatchDagRunStateData; + }; + "/public/providers/": { + get: { + req: GetProvidersData; res: { /** * Successful Response */ - 200: DAGRunResponse; - /** - * Bad Request - */ - 400: HTTPExceptionResponse; - /** - * Unauthorized - */ - 401: HTTPExceptionResponse; + 200: ProviderCollectionResponse; /** - * Forbidden + * Validation Error */ - 403: HTTPExceptionResponse; + 422: HTTPValidationError; + }; + }; + }; + "/public/plugins/": { + get: { + req: GetPluginsData; + res: { /** - * Not Found + * Successful Response */ - 404: HTTPExceptionResponse; + 200: PluginCollectionResponse; /** * Validation Error */ @@ -1287,28 +1384,24 @@ export type $OpenApiTs = { }; }; }; - "/public/monitor/health": { + "/public/version/": { get: { res: { /** * Successful Response */ - 200: HealthInfoSchema; + 200: VersionInfo; }; }; }; - "/public/pools/{pool_name}": { - delete: { - req: DeletePoolData; + "/public/eventLogs/{event_log_id}": { + get: { + req: GetEventLogData; res: { /** * Successful Response */ - 204: void; - /** - * Bad Request - */ - 400: HTTPExceptionResponse; + 200: EventLogResponse; /** * Unauthorized */ @@ -1327,13 +1420,15 @@ export type $OpenApiTs = { 422: HTTPValidationError; }; }; - get: { - req: GetPoolData; + }; + "/public/variables/{variable_key}": { + delete: { + req: DeleteVariableData; res: { /** * Successful Response */ - 200: PoolResponse; + 204: void; /** * Unauthorized */ @@ -1352,17 +1447,13 @@ export type $OpenApiTs = { 422: HTTPValidationError; }; }; - patch: { - req: PatchPoolData; + get: { + req: GetVariableData; res: { /** * Successful Response */ - 200: PoolResponse; - /** - * Bad Request - */ - 400: HTTPExceptionResponse; + 200: VariableResponse; /** * Unauthorized */ @@ -1381,15 +1472,17 @@ export type $OpenApiTs = { 422: HTTPValidationError; }; }; - }; - "/public/pools/": { - get: { - req: GetPoolsData; + patch: { + req: PatchVariableData; res: { /** * Successful Response */ - 200: PoolCollectionResponse; + 200: VariableResponse; + /** + * Bad Request + */ + 400: HTTPExceptionResponse; /** * Unauthorized */ @@ -1408,13 +1501,15 @@ export type $OpenApiTs = { 422: HTTPValidationError; }; }; - post: { - req: PostPoolData; + }; + "/public/variables/": { + get: { + req: GetVariablesData; res: { /** * Successful Response */ - 201: PoolResponse; + 200: VariableCollectionResponse; /** * Unauthorized */ @@ -1429,55 +1524,13 @@ export type $OpenApiTs = { 422: HTTPValidationError; }; }; - }; - "/public/providers/": { - get: { - req: GetProvidersData; - res: { - /** - * Successful Response - */ - 200: ProviderCollectionResponse; - /** - * Validation Error - */ - 422: HTTPValidationError; - }; - }; - }; - "/public/plugins/": { - get: { - req: GetPluginsData; - res: { - /** - * Successful Response - */ - 200: PluginCollectionResponse; - /** - * Validation Error - */ - 422: HTTPValidationError; - }; - }; - }; - "/public/version/": { - get: { - res: { - /** - * Successful Response - */ - 200: VersionInfo; - }; - }; - }; - "/public/eventLogs/{event_log_id}": { - get: { - req: GetEventLogData; + post: { + req: PostVariableData; res: { /** * Successful Response */ - 200: EventLogResponse; + 201: VariableResponse; /** * Unauthorized */ @@ -1486,10 +1539,6 @@ export type $OpenApiTs = { * Forbidden */ 403: HTTPExceptionResponse; - /** - * Not Found - */ - 404: HTTPExceptionResponse; /** * Validation Error */ diff --git a/tests/api_fastapi/core_api/routes/public/test_dag_sources.py b/tests/api_fastapi/core_api/routes/public/test_dag_sources.py new file mode 100644 index 000000000000..23a246073c35 --- /dev/null +++ b/tests/api_fastapi/core_api/routes/public/test_dag_sources.py @@ -0,0 +1,110 @@ +# 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 ast +import json +import os + +import pytest +from httpx import Response + +from airflow.models.dag import DAG +from airflow.models.dagbag import DagBag + +from tests_common.test_utils.db import clear_db_dag_code, clear_db_dags, clear_db_serialized_dags + +pytestmark = pytest.mark.db_test + +API_PREFIX = "/public/dagSources" + +# Example bash operator located here: airflow/example_dags/example_bash_operator.py +EXAMPLE_DAG_FILE = os.path.join("airflow", "example_dags", "example_bash_operator.py") +TEST_DAG_ID = "latest_only" + + +class TestGetDAGSource: + @pytest.fixture(autouse=True) + def setup(self, url_safe_serializer) -> None: + self.clear_db() + self.test_dag, self.dag_docstring = self.create_dag_source() + fileloc = url_safe_serializer.dumps(self.test_dag.fileloc) + self.dag_sources_url = f"{API_PREFIX}/{fileloc}" + + def teardown_method(self) -> None: + self.clear_db() + + @staticmethod + def _get_dag_file_docstring(fileloc: str) -> str | None: + with open(fileloc) as f: + file_contents = f.read() + module = ast.parse(file_contents) + docstring = ast.get_docstring(module) + return docstring + + def create_dag_source(self) -> tuple[DAG, str | None]: + dagbag = DagBag(dag_folder=EXAMPLE_DAG_FILE) + dagbag.sync_to_db() + test_dag: DAG = dagbag.dags[TEST_DAG_ID] + return test_dag, self._get_dag_file_docstring(test_dag.fileloc) + + def clear_db(self): + clear_db_dags() + clear_db_serialized_dags() + clear_db_dag_code() + + def test_should_respond_200_text(self, test_client): + response: Response = test_client.get(self.dag_sources_url, headers={"Accept": "text/plain"}) + + assert isinstance(response, Response) + assert 200 == response.status_code + assert len(self.dag_docstring) > 0 + assert self.dag_docstring in response.content.decode() + with pytest.raises(json.JSONDecodeError): + json.loads(response.content.decode()) + assert response.headers["Content-Type"].startswith("text/plain") + + @pytest.mark.parametrize("headers", [{"Accept": "application/json"}, {}]) + def test_should_respond_200_json(self, test_client, headers): + response: Response = test_client.get( + self.dag_sources_url, + headers=headers, + ) + assert isinstance(response, Response) + assert 200 == response.status_code + assert len(self.dag_docstring) > 0 + res_json = response.json() + assert isinstance(res_json, dict) + assert len(res_json.keys()) == 1 + assert len(res_json["content"]) > 0 + assert isinstance(res_json["content"], str) + assert self.dag_docstring in res_json["content"] + assert response.headers["Content-Type"].startswith("application/json") + + def test_should_respond_406_unsupport_mime_type(self, test_client): + response = test_client.get( + self.dag_sources_url, + headers={"Accept": "text/html"}, + ) + assert 406 == response.status_code + + def test_should_respond_404(self, test_client): + wrong_fileloc = "abcd1234" + url = f"{API_PREFIX}/{wrong_fileloc}" + response = test_client.get(url, headers={"Accept": "application/json"}) + assert 404 == response.status_code