diff --git a/airflow/www/package.json b/airflow/www/package.json index 22b6f882d3ed7..ef24c53a78ac8 100644 --- a/airflow/www/package.json +++ b/airflow/www/package.json @@ -51,6 +51,7 @@ "@testing-library/jest-dom": "^5.16.0", "@testing-library/react": "^13.0.0", "@types/color": "^3.0.3", + "@types/json-to-pretty-yaml": "^1.2.1", "@types/react": "^18.0.12", "@types/react-dom": "^18.0.5", "@types/react-syntax-highlighter": "^15.5.6", @@ -126,11 +127,12 @@ "framer-motion": "^6.0.0", "jquery": ">=3.5.0", "jshint": "^2.13.4", + "json-to-pretty-yaml": "^1.2.2", "lodash": "^4.17.21", "moment-timezone": "^0.5.43", "react": "^18.0.0", "react-dom": "^18.0.0", - "react-icons": "^4.9.0", + "react-icons": "^5.1.0", "react-json-view": "^1.21.3", "react-markdown": "^8.0.4", "react-query": "^3.39.1", diff --git a/airflow/www/static/js/api/index.ts b/airflow/www/static/js/api/index.ts index 4ba363a75cf11..c9bc4ed4c8cc5 100644 --- a/airflow/www/static/js/api/index.ts +++ b/airflow/www/static/js/api/index.ts @@ -53,6 +53,7 @@ import { useTaskXcomEntry, useTaskXcomCollection } from "./useTaskXcom"; import useEventLogs from "./useEventLogs"; import useCalendarData from "./useCalendarData"; import useCreateDatasetEvent from "./useCreateDatasetEvent"; +import useRenderedK8s from "./useRenderedK8s"; axios.interceptors.request.use((config) => { config.paramsSerializer = { @@ -102,4 +103,5 @@ export { useEventLogs, useCalendarData, useCreateDatasetEvent, + useRenderedK8s, }; diff --git a/airflow/www/static/js/api/useRenderedK8s.ts b/airflow/www/static/js/api/useRenderedK8s.ts new file mode 100644 index 0000000000000..1b1828e569a09 --- /dev/null +++ b/airflow/www/static/js/api/useRenderedK8s.ts @@ -0,0 +1,43 @@ +/*! + * 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. + */ + +import axios, { AxiosResponse } from "axios"; +import { useQuery } from "react-query"; + +import { getMetaValue } from "src/utils"; + +const url = getMetaValue("rendered_k8s_data_url"); + +const useRenderedK8s = ( + runId: string | null, + taskId: string | null, + mapIndex?: number +) => + useQuery( + ["rendered_k8s", runId, taskId, mapIndex], + async () => + axios.get(url, { + params: { run_id: runId, task_id: taskId, map_index: mapIndex }, + }), + { + enabled: !!runId && !!taskId, + } + ); + +export default useRenderedK8s; diff --git a/airflow/www/static/js/dag/details/index.tsx b/airflow/www/static/js/dag/details/index.tsx index 954792f9683f2..33d2b68ef4005 100644 --- a/airflow/www/static/js/dag/details/index.tsx +++ b/airflow/www/static/js/dag/details/index.tsx @@ -45,7 +45,7 @@ import { MdPlagiarism, MdEvent, } from "react-icons/md"; -import { BiBracket } from "react-icons/bi"; +import { BiBracket, BiLogoKubernetes } from "react-icons/bi"; import URLSearchParamsWrapper from "src/utils/URLSearchParamWrapper"; import Header from "./Header"; @@ -68,6 +68,7 @@ import TaskDetails from "./task"; import AuditLog from "./AuditLog"; import RunDuration from "./dag/RunDuration"; import Calendar from "./dag/Calendar"; +import RenderedK8s from "./taskInstance/RenderedK8s"; const dagId = getMetaValue("dag_id")!; @@ -79,6 +80,8 @@ interface Props { ganttScrollRef: React.RefObject; } +const isK8sExecutor = getMetaValue("k8s_or_k8scelery_executor") === "True"; + const tabToIndex = (tab?: string) => { switch (tab) { case "graph": @@ -96,6 +99,8 @@ const tabToIndex = (tab?: string) => { case "xcom": case "calendar": return 6; + case "rendered_k8s": + return 7; case "details": default: return 0; @@ -135,6 +140,9 @@ const indexToTab = ( if (!runId && !taskId) return "calendar"; if (isTaskInstance) return "xcom"; return undefined; + case 7: + if (isTaskInstance && isK8sExecutor) return "rendered_k8s"; + return undefined; default: return undefined; } @@ -360,6 +368,14 @@ const Details = ({ )} + {isTaskInstance && isK8sExecutor && ( + + + + K8s Pod Spec + + + )} {/* Match the styling of a tab but its actually a button */} {!!taskId && !!runId && (