diff --git a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py index a6df211746475..0d963678b6642 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py +++ b/airflow-core/src/airflow/api_fastapi/core_api/datamodels/dags.py @@ -155,6 +155,7 @@ class DAGDetailsResponse(DAGResponse): template_search_path: Iterable[str] | None timezone: str | None last_parsed: datetime | None + owner_links: dict[str, str] | None = None @field_validator("timezone", mode="before") @classmethod diff --git a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v1-rest-api-generated.yaml b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v1-rest-api-generated.yaml index 4ea3c207c3f06..5a6b37efa96b4 100644 --- a/airflow-core/src/airflow/api_fastapi/core_api/openapi/v1-rest-api-generated.yaml +++ b/airflow-core/src/airflow/api_fastapi/core_api/openapi/v1-rest-api-generated.yaml @@ -7887,6 +7887,13 @@ components: format: date-time - type: 'null' title: Last Parsed + owner_links: + anyOf: + - additionalProperties: + type: string + type: object + - type: 'null' + title: Owner Links file_token: type: string title: File Token diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts index 179da51471303..71358efef679e 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/schemas.gen.ts @@ -1715,6 +1715,20 @@ export const $DAGDetailsResponse = { ], title: "Last Parsed", }, + owner_links: { + anyOf: [ + { + additionalProperties: { + type: "string", + }, + type: "object", + }, + { + type: "null", + }, + ], + title: "Owner Links", + }, file_token: { type: "string", title: "File Token", diff --git a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts index d34e86cdb55bb..58d0419175282 100644 --- a/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts +++ b/airflow-core/src/airflow/ui/openapi-gen/requests/types.gen.ts @@ -471,6 +471,9 @@ export type DAGDetailsResponse = { template_search_path: Array | null; timezone: string | null; last_parsed: string | null; + owner_links?: { + [key: string]: string; + } | null; /** * Return file token. */ diff --git a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dags.py b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dags.py index d179a2fa39a39..def4656f850ba 100644 --- a/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dags.py +++ b/airflow-core/tests/unit/api_fastapi/core_api/routes/public/test_dags.py @@ -386,15 +386,22 @@ class TestDagDetails(TestDagEndpoint): """Unit tests for DAG Details.""" @pytest.mark.parametrize( - "query_params, dag_id, expected_status_code, dag_display_name, start_date", + "query_params, dag_id, expected_status_code, dag_display_name, start_date, owner_links", [ - ({}, "fake_dag_id", 404, "fake_dag", "2023-12-31T00:00:00Z"), - ({}, DAG2_ID, 200, DAG2_ID, "2021-06-15T00:00:00Z"), + ({}, "fake_dag_id", 404, "fake_dag", "2023-12-31T00:00:00Z", {}), + ({}, DAG2_ID, 200, DAG2_ID, "2021-06-15T00:00:00Z", {}), ], ) @pytest.mark.usefixtures("configure_git_connection_for_dag_bundle") def test_dag_details( - self, test_client, query_params, dag_id, expected_status_code, dag_display_name, start_date + self, + test_client, + query_params, + dag_id, + expected_status_code, + dag_display_name, + start_date, + owner_links, ): response = test_client.get(f"/dags/{dag_id}/details", params=query_params) assert response.status_code == expected_status_code @@ -445,6 +452,7 @@ def test_dag_details( "next_dagrun_logical_date": None, "next_dagrun_run_after": None, "owners": ["airflow"], + "owner_links": {}, "params": { "foo": { "__class": "airflow.sdk.definitions.param.Param", diff --git a/airflow-ctl/src/airflowctl/api/datamodels/generated.py b/airflow-ctl/src/airflowctl/api/datamodels/generated.py index b2f97ae42bf05..81c1066495dfd 100644 --- a/airflow-ctl/src/airflowctl/api/datamodels/generated.py +++ b/airflow-ctl/src/airflowctl/api/datamodels/generated.py @@ -1144,6 +1144,7 @@ class DAGDetailsResponse(BaseModel): template_search_path: Annotated[list[str] | None, Field(title="Template Search Path")] = None timezone: Annotated[str | None, Field(title="Timezone")] = None last_parsed: Annotated[datetime | None, Field(title="Last Parsed")] = None + owner_links: Annotated[dict[str, str] | None, Field(title="Owner Links")] = None file_token: Annotated[str, Field(description="Return file token.", title="File Token")] concurrency: Annotated[ int, Field(description="Return max_active_tasks as concurrency.", title="Concurrency")