This is an automated email from the ASF dual-hosted git repository. bbovenzi pushed a commit to branch fix-grid-errors in repository https://gitbox.apache.org/repos/asf/airflow.git
commit b84599b99cd8f9803fae8f2b5c5b98577182560a Author: Brent Bovenzi <[email protected]> AuthorDate: Thu Apr 21 11:56:40 2022 -0400 Fix grid error handling --- airflow/www/static/js/tree/api/useClearRun.js | 23 +++------ airflow/www/static/js/tree/api/useClearTask.js | 23 +++------ airflow/www/static/js/tree/api/useMarkFailedRun.js | 3 ++ .../www/static/js/tree/api/useMarkFailedTask.js | 3 ++ .../www/static/js/tree/api/useMarkSuccessRun.js | 3 ++ .../www/static/js/tree/api/useMarkSuccessTask.js | 3 ++ airflow/www/static/js/tree/api/useQueueRun.js | 3 ++ airflow/www/static/js/tree/api/useRunTask.js | 23 +++------ airflow/www/static/js/tree/api/useTreeData.js | 15 +++--- .../js/tree/details/content/dagRun/ClearRun.jsx | 20 +++----- .../tree/details/content/dagRun/MarkFailedRun.jsx | 10 ++-- .../tree/details/content/dagRun/MarkSuccessRun.jsx | 20 +++----- .../js/tree/details/content/dagRun/QueueRun.jsx | 20 +++----- .../content/taskInstance/taskActions/Clear.jsx | 56 ++++++++++------------ .../taskInstance/taskActions/MarkFailed.jsx | 44 +++++++---------- .../taskInstance/taskActions/MarkSuccess.jsx | 44 +++++++---------- airflow/www/static/js/tree/useErrorToast.js | 46 ++++++++++++++++++ airflow/www/views.py | 24 +++++----- 18 files changed, 182 insertions(+), 201 deletions(-) diff --git a/airflow/www/static/js/tree/api/useClearRun.js b/airflow/www/static/js/tree/api/useClearRun.js index 9a5c21a8aa..afcb620c3a 100644 --- a/airflow/www/static/js/tree/api/useClearRun.js +++ b/airflow/www/static/js/tree/api/useClearRun.js @@ -18,17 +18,17 @@ */ import axios from 'axios'; -import { useToast } from '@chakra-ui/react'; import { useMutation, useQueryClient } from 'react-query'; import { getMetaValue } from '../../utils'; import { useAutoRefresh } from '../context/autorefresh'; +import useErrorToast from '../useErrorToast'; const csrfToken = getMetaValue('csrf_token'); const clearRunUrl = getMetaValue('dagrun_clear_url'); export default function useClearRun(dagId, runId) { const queryClient = useQueryClient(); - const toast = useToast(); + const errorToast = useErrorToast(); const { startRefresh } = useAutoRefresh(); return useMutation( ['dagRunClear', dagId, runId], @@ -47,21 +47,12 @@ export default function useClearRun(dagId, runId) { }); }, { - onSuccess: (data) => { - const { message, status } = data; - if (message && status === 'error') { - toast({ - description: message, - isClosable: true, - status, - }); - } - if (!status || status !== 'error') { - // Invalidating the query will force a new API request - queryClient.invalidateQueries('treeData'); - startRefresh(); - } + onSuccess: () => { + // Invalidating the query will force a new API request + queryClient.invalidateQueries('treeData'); + startRefresh(); }, + onError: (error) => errorToast({ error }), }, ); } diff --git a/airflow/www/static/js/tree/api/useClearTask.js b/airflow/www/static/js/tree/api/useClearTask.js index 2ea3eee486..777a621aaf 100644 --- a/airflow/www/static/js/tree/api/useClearTask.js +++ b/airflow/www/static/js/tree/api/useClearTask.js @@ -18,10 +18,10 @@ */ import axios from 'axios'; -import { useToast } from '@chakra-ui/react'; import { useMutation, useQueryClient } from 'react-query'; import { getMetaValue } from '../../utils'; import { useAutoRefresh } from '../context/autorefresh'; +import useErrorToast from '../useErrorToast'; const csrfToken = getMetaValue('csrf_token'); const clearUrl = getMetaValue('clear_url'); @@ -30,7 +30,7 @@ export default function useClearTask({ dagId, runId, taskId, executionDate, }) { const queryClient = useQueryClient(); - const toast = useToast(); + const errorToast = useErrorToast(); const { startRefresh } = useAutoRefresh(); return useMutation( @@ -64,21 +64,12 @@ export default function useClearTask({ }); }, { - onSuccess: (data) => { - const { message, status } = data; - if (message && status === 'error') { - toast({ - description: message, - isClosable: true, - status, - }); - } - if (!status || status !== 'error') { - queryClient.invalidateQueries('treeData'); - queryClient.invalidateQueries('mappedInstances', dagId, runId, taskId); - startRefresh(); - } + onSuccess: () => { + queryClient.invalidateQueries('treeData'); + queryClient.invalidateQueries('mappedInstances', dagId, runId, taskId); + startRefresh(); }, + onError: (error) => errorToast({ error }), }, ); } diff --git a/airflow/www/static/js/tree/api/useMarkFailedRun.js b/airflow/www/static/js/tree/api/useMarkFailedRun.js index 725d9907db..c7487be5e9 100644 --- a/airflow/www/static/js/tree/api/useMarkFailedRun.js +++ b/airflow/www/static/js/tree/api/useMarkFailedRun.js @@ -21,12 +21,14 @@ import axios from 'axios'; import { useMutation, useQueryClient } from 'react-query'; import { getMetaValue } from '../../utils'; import { useAutoRefresh } from '../context/autorefresh'; +import useErrorToast from '../useErrorToast'; const csrfToken = getMetaValue('csrf_token'); const markFailedUrl = getMetaValue('dagrun_failed_url'); export default function useMarkFailedRun(dagId, runId) { const queryClient = useQueryClient(); + const errorToast = useErrorToast(); const { startRefresh } = useAutoRefresh(); return useMutation( ['dagRunFailed', dagId, runId], @@ -49,6 +51,7 @@ export default function useMarkFailedRun(dagId, runId) { queryClient.invalidateQueries('treeData'); startRefresh(); }, + onError: (error) => errorToast({ error }), }, ); } diff --git a/airflow/www/static/js/tree/api/useMarkFailedTask.js b/airflow/www/static/js/tree/api/useMarkFailedTask.js index a94ab22d0c..4ef72df1ba 100644 --- a/airflow/www/static/js/tree/api/useMarkFailedTask.js +++ b/airflow/www/static/js/tree/api/useMarkFailedTask.js @@ -21,6 +21,7 @@ import axios from 'axios'; import { useMutation, useQueryClient } from 'react-query'; import { getMetaValue } from '../../utils'; import { useAutoRefresh } from '../context/autorefresh'; +import useErrorToast from '../useErrorToast'; const failedUrl = getMetaValue('failed_url'); const csrfToken = getMetaValue('csrf_token'); @@ -29,6 +30,7 @@ export default function useMarkFailedTask({ dagId, runId, taskId, }) { const queryClient = useQueryClient(); + const errorToast = useErrorToast(); const { startRefresh } = useAutoRefresh(); return useMutation( ['markFailed', dagId, runId, taskId], @@ -63,6 +65,7 @@ export default function useMarkFailedTask({ queryClient.invalidateQueries('mappedInstances', dagId, runId, taskId); startRefresh(); }, + onError: (error) => errorToast({ error }), }, ); } diff --git a/airflow/www/static/js/tree/api/useMarkSuccessRun.js b/airflow/www/static/js/tree/api/useMarkSuccessRun.js index 9f769c997c..6076e6ba1e 100644 --- a/airflow/www/static/js/tree/api/useMarkSuccessRun.js +++ b/airflow/www/static/js/tree/api/useMarkSuccessRun.js @@ -21,12 +21,14 @@ import axios from 'axios'; import { useMutation, useQueryClient } from 'react-query'; import { getMetaValue } from '../../utils'; import { useAutoRefresh } from '../context/autorefresh'; +import useErrorToast from '../useErrorToast'; const markSuccessUrl = getMetaValue('dagrun_success_url'); const csrfToken = getMetaValue('csrf_token'); export default function useMarkSuccessRun(dagId, runId) { const queryClient = useQueryClient(); + const errorToast = useErrorToast(); const { startRefresh } = useAutoRefresh(); return useMutation( ['dagRunSuccess', dagId, runId], @@ -49,6 +51,7 @@ export default function useMarkSuccessRun(dagId, runId) { queryClient.invalidateQueries('treeData'); startRefresh(); }, + onError: (error) => errorToast({ error }), }, ); } diff --git a/airflow/www/static/js/tree/api/useMarkSuccessTask.js b/airflow/www/static/js/tree/api/useMarkSuccessTask.js index 47fda2f0f8..14d83e653d 100644 --- a/airflow/www/static/js/tree/api/useMarkSuccessTask.js +++ b/airflow/www/static/js/tree/api/useMarkSuccessTask.js @@ -21,6 +21,7 @@ import axios from 'axios'; import { useMutation, useQueryClient } from 'react-query'; import { getMetaValue } from '../../utils'; import { useAutoRefresh } from '../context/autorefresh'; +import useErrorToast from '../useErrorToast'; const csrfToken = getMetaValue('csrf_token'); const successUrl = getMetaValue('success_url'); @@ -29,6 +30,7 @@ export default function useMarkSuccessTask({ dagId, runId, taskId, }) { const queryClient = useQueryClient(); + const errorToast = useErrorToast(); const { startRefresh } = useAutoRefresh(); return useMutation( ['markSuccess', dagId, runId, taskId], @@ -64,6 +66,7 @@ export default function useMarkSuccessTask({ queryClient.invalidateQueries('mappedInstances', dagId, runId, taskId); startRefresh(); }, + onError: (error) => errorToast({ error }), }, ); } diff --git a/airflow/www/static/js/tree/api/useQueueRun.js b/airflow/www/static/js/tree/api/useQueueRun.js index 20612f1142..5848d680f9 100644 --- a/airflow/www/static/js/tree/api/useQueueRun.js +++ b/airflow/www/static/js/tree/api/useQueueRun.js @@ -21,12 +21,14 @@ import axios from 'axios'; import { useMutation, useQueryClient } from 'react-query'; import { getMetaValue } from '../../utils'; import { useAutoRefresh } from '../context/autorefresh'; +import useErrorToast from '../useErrorToast'; const csrfToken = getMetaValue('csrf_token'); const queuedUrl = getMetaValue('dagrun_queued_url'); export default function useQueueRun(dagId, runId) { const queryClient = useQueryClient(); + const errorToast = useErrorToast(); const { startRefresh } = useAutoRefresh(); return useMutation( ['dagRunQueue', dagId, runId], @@ -49,6 +51,7 @@ export default function useQueueRun(dagId, runId) { queryClient.invalidateQueries('treeData'); startRefresh(); }, + onError: (error) => errorToast({ error }), }, ); } diff --git a/airflow/www/static/js/tree/api/useRunTask.js b/airflow/www/static/js/tree/api/useRunTask.js index 9e45c42f59..810b2dceab 100644 --- a/airflow/www/static/js/tree/api/useRunTask.js +++ b/airflow/www/static/js/tree/api/useRunTask.js @@ -18,17 +18,17 @@ */ import axios from 'axios'; -import { useToast } from '@chakra-ui/react'; import { useMutation, useQueryClient } from 'react-query'; import { getMetaValue } from '../../utils'; import { useAutoRefresh } from '../context/autorefresh'; +import useErrorToast from '../useErrorToast'; const csrfToken = getMetaValue('csrf_token'); const runUrl = getMetaValue('run_url'); export default function useRunTask(dagId, runId, taskId) { const queryClient = useQueryClient(); - const toast = useToast(); + const errorToast = useErrorToast(); const { startRefresh } = useAutoRefresh(); return useMutation( ['runTask', dagId, runId, taskId], @@ -58,21 +58,12 @@ export default function useRunTask(dagId, runId, taskId) { }), ), { - onSuccess: (data) => { - const { message, status } = data.length ? data[0] : data; - if (message && status === 'error') { - toast({ - description: message, - isClosable: true, - status, - }); - } - if (!status || status !== 'error') { - queryClient.invalidateQueries('treeData'); - queryClient.invalidateQueries('mappedInstances', dagId, runId, taskId); - startRefresh(); - } + onSuccess: () => { + queryClient.invalidateQueries('treeData'); + queryClient.invalidateQueries('mappedInstances', dagId, runId, taskId); + startRefresh(); }, + onError: (error) => errorToast({ error }), }, ); } diff --git a/airflow/www/static/js/tree/api/useTreeData.js b/airflow/www/static/js/tree/api/useTreeData.js index ddb0a9dfed..a33e17c1c4 100644 --- a/airflow/www/static/js/tree/api/useTreeData.js +++ b/airflow/www/static/js/tree/api/useTreeData.js @@ -21,11 +21,11 @@ import { useQuery } from 'react-query'; import axios from 'axios'; -import { useToast } from '@chakra-ui/react'; import { getMetaValue } from '../../utils'; import { useAutoRefresh } from '../context/autorefresh'; import { formatData, areActiveRuns } from '../treeDataUtils'; +import useErrorToast from '../useErrorToast'; // dagId comes from dag.html const dagId = getMetaValue('dag_id'); @@ -41,7 +41,7 @@ const useTreeData = () => { }; const initialData = formatData(treeData, emptyData); const { isRefreshOn, stopRefresh } = useAutoRefresh(); - const toast = useToast(); + const errorToast = useErrorToast(); return useQuery('treeData', async () => { try { const root = urlRoot ? `&root=${urlRoot}` : ''; @@ -50,16 +50,13 @@ const useTreeData = () => { // turn off auto refresh if there are no active runs if (!areActiveRuns(newData.dagRuns)) stopRefresh(); return newData; - } catch (e) { + } catch (error) { stopRefresh(); - // Display error in a toast message - toast({ + errorToast({ title: 'Auto-refresh Error', - description: e.message, - isClosable: true, - status: 'error', + error, }); - throw (e); + throw (error); } }, { // only enabled and refetch if the refresh switch is on diff --git a/airflow/www/static/js/tree/details/content/dagRun/ClearRun.jsx b/airflow/www/static/js/tree/details/content/dagRun/ClearRun.jsx index bbd7ffba42..95aed65f8c 100644 --- a/airflow/www/static/js/tree/details/content/dagRun/ClearRun.jsx +++ b/airflow/www/static/js/tree/details/content/dagRun/ClearRun.jsx @@ -29,23 +29,15 @@ const ClearRun = ({ dagId, runId }) => { const { mutateAsync: onClear, isLoading } = useClearRun(dagId, runId); const onClick = async () => { - try { - const data = await onClear({ confirmed: false }); - setAffectedTasks(data); - onOpen(); - } catch (e) { - console.error(e); - } + const data = await onClear({ confirmed: false }); + setAffectedTasks(data); + onOpen(); }; const onConfirm = async () => { - try { - await onClear({ confirmed: true }); - setAffectedTasks([]); - onClose(); - } catch (e) { - console.error(e); - } + await onClear({ confirmed: true }); + setAffectedTasks([]); + onClose(); }; return ( diff --git a/airflow/www/static/js/tree/details/content/dagRun/MarkFailedRun.jsx b/airflow/www/static/js/tree/details/content/dagRun/MarkFailedRun.jsx index 226643a77b..483dbd4fe0 100644 --- a/airflow/www/static/js/tree/details/content/dagRun/MarkFailedRun.jsx +++ b/airflow/www/static/js/tree/details/content/dagRun/MarkFailedRun.jsx @@ -29,13 +29,9 @@ const MarkFailedRun = ({ dagId, runId }) => { const { mutateAsync: markFailed, isLoading } = useMarkFailedRun(dagId, runId); const onClick = async () => { - try { - const data = await markFailed({ confirmed: false }); - setAffectedTasks(data); - onOpen(); - } catch (error) { - console.error(error); - } + const data = await markFailed({ confirmed: false }); + setAffectedTasks(data); + onOpen(); }; const onConfirm = () => { diff --git a/airflow/www/static/js/tree/details/content/dagRun/MarkSuccessRun.jsx b/airflow/www/static/js/tree/details/content/dagRun/MarkSuccessRun.jsx index 30715c340b..0d1d8483d3 100644 --- a/airflow/www/static/js/tree/details/content/dagRun/MarkSuccessRun.jsx +++ b/airflow/www/static/js/tree/details/content/dagRun/MarkSuccessRun.jsx @@ -29,23 +29,15 @@ const MarkSuccessRun = ({ dagId, runId }) => { const { mutateAsync: markSuccess, isLoading } = useMarkSuccessRun(dagId, runId); const onClick = async () => { - try { - const data = await markSuccess({ confirmed: false }); - setAffectedTasks(data); - onOpen(); - } catch (e) { - console.error(e); - } + const data = await markSuccess({ confirmed: false }); + setAffectedTasks(data); + onOpen(); }; const onConfirm = async () => { - try { - await markSuccess({ confirmed: true }); - setAffectedTasks([]); - onClose(); - } catch (e) { - console.error(e); - } + await markSuccess({ confirmed: true }); + setAffectedTasks([]); + onClose(); }; return ( diff --git a/airflow/www/static/js/tree/details/content/dagRun/QueueRun.jsx b/airflow/www/static/js/tree/details/content/dagRun/QueueRun.jsx index ef87d9fea5..ceec45ffdd 100644 --- a/airflow/www/static/js/tree/details/content/dagRun/QueueRun.jsx +++ b/airflow/www/static/js/tree/details/content/dagRun/QueueRun.jsx @@ -30,24 +30,16 @@ const QueueRun = ({ dagId, runId }) => { // Get what the changes will be and show it in a modal const onClick = async () => { - try { - const data = await onQueue({ confirmed: false }); - setAffectedTasks(data); - onOpen(); - } catch (e) { - console.error(e); - } + const data = await onQueue({ confirmed: false }); + setAffectedTasks(data); + onOpen(); }; // Confirm changes const onConfirm = async () => { - try { - await onQueue({ confirmed: true }); - setAffectedTasks([]); - onClose(); - } catch (e) { - console.error(e); - } + await onQueue({ confirmed: true }); + setAffectedTasks([]); + onClose(); }; return ( diff --git a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Clear.jsx b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Clear.jsx index d825976ed2..de972c3f2f 100644 --- a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Clear.jsx +++ b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/Clear.jsx @@ -65,41 +65,33 @@ const Run = ({ }); const onClick = async () => { - try { - const data = await clearTask({ - past, - future, - upstream, - downstream, - recursive, - failed, - confirmed: false, - mapIndexes, - }); - setAffectedTasks(data); - onOpen(); - } catch (e) { - console.error(e); - } + const data = await clearTask({ + past, + future, + upstream, + downstream, + recursive, + failed, + confirmed: false, + mapIndexes, + }); + setAffectedTasks(data); + onOpen(); }; const onConfirm = async () => { - try { - await clearTask({ - past, - future, - upstream, - downstream, - recursive, - failed, - confirmed: true, - mapIndexes, - }); - setAffectedTasks([]); - onClose(); - } catch (e) { - console.error(e); - } + await clearTask({ + past, + future, + upstream, + downstream, + recursive, + failed, + confirmed: true, + mapIndexes, + }); + setAffectedTasks([]); + onClose(); }; return ( diff --git a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkFailed.jsx b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkFailed.jsx index 12f8bcfeef..fd75d9664d 100644 --- a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkFailed.jsx +++ b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkFailed.jsx @@ -63,35 +63,27 @@ const MarkFailed = ({ }); const onClick = async () => { - try { - const data = await confirmChangeMutation({ - past, - future, - upstream, - downstream, - mapIndexes, - }); - setAffectedTasks(data); - onOpen(); - } catch (e) { - console.error(e); - } + const data = await confirmChangeMutation({ + past, + future, + upstream, + downstream, + mapIndexes, + }); + setAffectedTasks(data); + onOpen(); }; const onConfirm = async () => { - try { - await markFailedMutation({ - past, - future, - upstream, - downstream, - mapIndexes, - }); - setAffectedTasks([]); - onClose(); - } catch (e) { - console.error(e); - } + await markFailedMutation({ + past, + future, + upstream, + downstream, + mapIndexes, + }); + setAffectedTasks([]); + onClose(); }; return ( diff --git a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkSuccess.jsx b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkSuccess.jsx index bdf59e6a4d..515093f38d 100644 --- a/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkSuccess.jsx +++ b/airflow/www/static/js/tree/details/content/taskInstance/taskActions/MarkSuccess.jsx @@ -58,35 +58,27 @@ const MarkSuccess = ({ }); const onClick = async () => { - try { - const data = await confirmChangeMutation({ - past, - future, - upstream, - downstream, - mapIndexes, - }); - setAffectedTasks(data); - onOpen(); - } catch (e) { - console.error(e); - } + const data = await confirmChangeMutation({ + past, + future, + upstream, + downstream, + mapIndexes, + }); + setAffectedTasks(data); + onOpen(); }; const onConfirm = async () => { - try { - await markSuccessMutation({ - past, - future, - upstream, - downstream, - mapIndexes, - }); - setAffectedTasks([]); - onClose(); - } catch (e) { - console.error(e); - } + await markSuccessMutation({ + past, + future, + upstream, + downstream, + mapIndexes, + }); + setAffectedTasks([]); + onClose(); }; return ( diff --git a/airflow/www/static/js/tree/useErrorToast.js b/airflow/www/static/js/tree/useErrorToast.js new file mode 100644 index 0000000000..02d3195f6c --- /dev/null +++ b/airflow/www/static/js/tree/useErrorToast.js @@ -0,0 +1,46 @@ +/*! + * 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 { useToast } from '@chakra-ui/react'; + +const getErrorDescription = (error, fallbackMessage) => { + if (error.response && error.response.data) { + return error.response.data; + } + if (error instanceof Error) return error.message; + if (typeof error === 'string') return error; + return fallbackMessage || 'Something went wrong.'; +}; + +const getErrorTitle = (error) => (error.message || 'Error'); + +const useErrorToast = () => { + const toast = useToast(); + // Add an error prop and handle it as a description + return ({ error, ...rest }) => { + toast({ + status: 'error', + title: getErrorTitle(error), + description: getErrorDescription(error).slice(0, 500), + ...rest, + }); + }; +}; + +export default useErrorToast; diff --git a/airflow/www/views.py b/airflow/www/views.py index ae0186e493..6113084876 100644 --- a/airflow/www/views.py +++ b/airflow/www/views.py @@ -513,13 +513,15 @@ def get_task_stats_from_query(qry): return data -def redirect_or_json(origin, msg, status=""): +def redirect_or_json(origin, msg, status="", status_code=200): """ Some endpoints are called by javascript, returning json will allow us to more elegantly handle side-effects in-page """ if request.headers.get('Accept') == 'application/json': - return {'status': status, 'message': msg} + if status == 'error' and status_code == 200: + status_code = 500 + return Response(response=msg, status=status_code, mimetype="application/json") else: if status: flash(msg, status) @@ -1757,13 +1759,13 @@ class Airflow(AirflowBaseView): if not getattr(executor, "supports_ad_hoc_ti_run", False): msg = "Only works with the Celery, CeleryKubernetes or Kubernetes executors" - return redirect_or_json(origin, msg, "error") + return redirect_or_json(origin, msg, "error", 400) dag_run = dag.get_dagrun(run_id=dag_run_id) ti = dag_run.get_task_instance(task_id=task.task_id, map_index=map_index) if not ti: msg = "Could not queue task instance for execution, task instance is missing" - return redirect_or_json(origin, msg, "error") + return redirect_or_json(origin, msg, "error", 400) ti.refresh_from_task(task) @@ -1778,7 +1780,7 @@ class Airflow(AirflowBaseView): if failed_deps: failed_deps_str = ", ".join(f"{dep.dep_name}: {dep.reason}" for dep in failed_deps) msg = f"Could not queue task instance for execution, dependencies not met: {failed_deps_str}" - return redirect_or_json(origin, msg, "error") + return redirect_or_json(origin, msg, "error", 400) executor.job_id = "manual" executor.start() @@ -1993,13 +1995,13 @@ class Airflow(AirflowBaseView): dry_run=True, ) except AirflowException as ex: - return redirect_or_json(origin, msg=str(ex), status="error") + return redirect_or_json(origin, msg=str(ex), status="error", status_code=500) assert isinstance(tis, collections.abc.Iterable) details = [str(t) for t in tis] if not details: - return redirect_or_json(origin, "No task instances to clear", status="error") + return redirect_or_json(origin, "No task instances to clear", status="error", status_code=404) elif request.headers.get('Accept') == 'application/json': return htmlsafe_json_dumps(details, separators=(',', ':')) return self.render_template( @@ -2353,13 +2355,13 @@ class Airflow(AirflowBaseView): dag = current_app.dag_bag.get_dag(dag_id) if not dag: msg = f'DAG {dag_id} not found' - return redirect_or_json(origin, msg, status='error') + return redirect_or_json(origin, msg, status='error', status_code=404) try: task = dag.get_task(task_id) except airflow.exceptions.TaskNotFound: msg = f"Task {task_id} not found" - return redirect_or_json(origin, msg, status='error') + return redirect_or_json(origin, msg, status='error', status_code=404) task.dag = dag @@ -2368,12 +2370,12 @@ class Airflow(AirflowBaseView): 'failed', ): msg = f"Invalid state {state}, must be either 'success' or 'failed'" - return redirect_or_json(origin, msg, status='error') + return redirect_or_json(origin, msg, status='error', status_code=400) latest_execution_date = dag.get_latest_execution_date() if not latest_execution_date: msg = f"Cannot mark tasks as {state}, seem that dag {dag_id} has never run" - return redirect_or_json(origin, msg, status='error') + return redirect_or_json(origin, msg, status='error', status_code=400) if map_indexes is None: tasks: Union[List[Operator], List[Tuple[Operator, int]]] = [task]
