From 149cc51fc102a7573313f20017e7c4d6119a3f04 Mon Sep 17 00:00:00 2001 From: Milton Hultgren Date: Thu, 5 Oct 2023 11:39:23 +0200 Subject: [PATCH] [infra] Use correct ML API to query blocking tasks (#167779) While working on https://github.com/elastic/kibana/issues/47477, I found that attempting to re-create a ML job faces a 404 because it uses an endpoint that has been removed / changed. This PR updates to use the newer endpoint to find which tasks are blocking in the ML system (like job deletion) and changes the types to match the new API. (cherry picked from commit 48b66d72dc8fc40fdf21a8c812cfd7659686ccf2) --- .../containers/logs/log_analysis/api/ml_cleanup.ts | 4 ++-- .../logs/log_analysis/log_analysis_cleanup.tsx | 6 ++++-- .../logs/log_analysis/log_analysis_module.tsx | 7 +++++-- .../logs/log_analysis/log_analysis_module_status.tsx | 4 ++-- .../infra/public/containers/ml/api/ml_cleanup.ts | 4 ++-- .../infra/public/containers/ml/infra_ml_cleanup.tsx | 6 ++++-- .../infra/public/containers/ml/infra_ml_module.tsx | 7 +++++-- .../public/containers/ml/infra_ml_module_status.tsx | 4 ++-- .../ml/anomaly_detection/job_setup_screen.tsx | 12 ++++++++++++ 9 files changed, 38 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/api/ml_cleanup.ts b/x-pack/plugins/infra/public/containers/logs/log_analysis/api/ml_cleanup.ts index e0cdd44bafe14..dd4fc9144976e 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/api/ml_cleanup.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/api/ml_cleanup.ts @@ -38,7 +38,7 @@ export const callDeleteJobs = async ( }; export const callGetJobDeletionTasks = async (fetch: HttpHandler) => { - const jobDeletionTasksResponse = await fetch('/internal/ml/jobs/deleting_jobs_tasks', { + const jobDeletionTasksResponse = await fetch('/internal/ml/jobs/blocking_jobs_tasks', { version: '1', }); @@ -87,7 +87,7 @@ export const deleteJobsResponsePayloadRT = rt.record( export type DeleteJobsResponsePayload = rt.TypeOf; export const getJobDeletionTasksResponsePayloadRT = rt.type({ - jobIds: rt.array(rt.string), + jobs: rt.array(rt.record(rt.string, rt.string)), }); export const stopDatafeedsRequestPayloadRT = rt.type({ diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_cleanup.tsx b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_cleanup.tsx index 2a5493f153ff3..b9668311df062 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_cleanup.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_cleanup.tsx @@ -46,8 +46,10 @@ const waitUntilJobsAreDeleted = async ( ) => { const moduleJobIds = jobTypes.map((jobType) => getJobId(spaceId, logViewId, jobType)); while (true) { - const { jobIds: jobIdsBeingDeleted } = await callGetJobDeletionTasks(fetch); - const needToWait = jobIdsBeingDeleted.some((jobId) => moduleJobIds.includes(jobId)); + const { jobs } = await callGetJobDeletionTasks(fetch); + const needToWait = jobs + .flatMap((job) => Object.keys(job)) + .some((jobId) => moduleJobIds.includes(jobId)); if (needToWait) { await timeout(1000); diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module.tsx b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module.tsx index 7224848ba2e90..58bade0a81d06 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module.tsx @@ -123,6 +123,9 @@ export const useLogAnalysisModule = ({ createPromise: async () => { return await moduleDescriptor.cleanUpModule(spaceId, logViewId, services.http.fetch); }, + onReject: (e) => { + throw new Error(`Failed to clean up previous ML job: ${e}`); + }, }, [spaceId, logViewId] ); @@ -144,8 +147,8 @@ export const useLogAnalysisModule = ({ .then(() => { setUpModule(selectedIndices, start, end, datasetFilter); }) - .catch(() => { - dispatchModuleStatus({ type: 'failedSetup' }); + .catch((e) => { + dispatchModuleStatus({ type: 'failedSetup', reason: e.toString() }); }); }, [cleanUpModule, dispatchModuleStatus, setUpModule] diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_status.tsx b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_status.tsx index 90f36b40d14d7..6fcfea1038a04 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_status.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_status.tsx @@ -35,7 +35,7 @@ type StatusReducerAction = jobSummaries: FetchJobStatusResponsePayload; datafeedSetupResults: SetupMlModuleResponsePayload['datafeeds']; } - | { type: 'failedSetup' } + | { type: 'failedSetup'; reason?: string } | { type: 'fetchingJobStatuses' } | { type: 'fetchedJobStatuses'; @@ -131,7 +131,7 @@ const createStatusReducer = }), {} as Record ), - setupStatus: { type: 'failed', reasons: ['unknown'] }, + setupStatus: { type: 'failed', reasons: action.reason ? [action.reason] : ['unknown'] }, }; } case 'fetchingJobStatuses': { diff --git a/x-pack/plugins/infra/public/containers/ml/api/ml_cleanup.ts b/x-pack/plugins/infra/public/containers/ml/api/ml_cleanup.ts index e2d22cd45bc11..d4e8152553244 100644 --- a/x-pack/plugins/infra/public/containers/ml/api/ml_cleanup.ts +++ b/x-pack/plugins/infra/public/containers/ml/api/ml_cleanup.ts @@ -37,7 +37,7 @@ export const callDeleteJobs = async ( }; export const callGetJobDeletionTasks = async (fetch: HttpHandler) => { - const jobDeletionTasksResponse = await fetch('/internal/ml/jobs/deleting_jobs_tasks', { + const jobDeletionTasksResponse = await fetch('/internal/ml/jobs/blocking_jobs_tasks', { version: '1', }); @@ -86,7 +86,7 @@ export const deleteJobsResponsePayloadRT = rt.record( export type DeleteJobsResponsePayload = rt.TypeOf; export const getJobDeletionTasksResponsePayloadRT = rt.type({ - jobIds: rt.array(rt.string), + jobs: rt.array(rt.record(rt.string, rt.string)), }); export const stopDatafeedsRequestPayloadRT = rt.type({ diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_cleanup.tsx b/x-pack/plugins/infra/public/containers/ml/infra_ml_cleanup.tsx index 87d367ea56ff3..a5c89e93b0f63 100644 --- a/x-pack/plugins/infra/public/containers/ml/infra_ml_cleanup.tsx +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_cleanup.tsx @@ -46,8 +46,10 @@ const waitUntilJobsAreDeleted = async ( ) => { const moduleJobIds = jobTypes.map((jobType) => getJobId(spaceId, sourceId, jobType)); while (true) { - const { jobIds: jobIdsBeingDeleted } = await callGetJobDeletionTasks(fetch); - const needToWait = jobIdsBeingDeleted.some((jobId) => moduleJobIds.includes(jobId)); + const { jobs } = await callGetJobDeletionTasks(fetch); + const needToWait = jobs + .flatMap((job) => Object.keys(job)) + .some((jobId) => moduleJobIds.includes(jobId)); if (needToWait) { await timeout(1000); diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_module.tsx b/x-pack/plugins/infra/public/containers/ml/infra_ml_module.tsx index 22376648ca003..e82c5423389b3 100644 --- a/x-pack/plugins/infra/public/containers/ml/infra_ml_module.tsx +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_module.tsx @@ -99,6 +99,9 @@ export const useInfraMLModule = ({ createPromise: async () => { return await moduleDescriptor.cleanUpModule(spaceId, sourceId, services.http.fetch); }, + onReject: (e) => { + throw new Error(`Failed to clean up previous ML job: ${e}`); + }, }, [spaceId, sourceId] ); @@ -121,8 +124,8 @@ export const useInfraMLModule = ({ .then(() => { setUpModule(selectedIndices, start, end, filter, partitionField); }) - .catch(() => { - dispatchModuleStatus({ type: 'failedSetup' }); + .catch((e) => { + dispatchModuleStatus({ type: 'failedSetup', reason: e.toString() }); }); }, [cleanUpModule, dispatchModuleStatus, setUpModule] diff --git a/x-pack/plugins/infra/public/containers/ml/infra_ml_module_status.tsx b/x-pack/plugins/infra/public/containers/ml/infra_ml_module_status.tsx index fc41e67c2bd2c..ea222080d410c 100644 --- a/x-pack/plugins/infra/public/containers/ml/infra_ml_module_status.tsx +++ b/x-pack/plugins/infra/public/containers/ml/infra_ml_module_status.tsx @@ -35,7 +35,7 @@ type StatusReducerAction = jobSummaries: FetchJobStatusResponsePayload; datafeedSetupResults: SetupMlModuleResponsePayload['datafeeds']; } - | { type: 'failedSetup' } + | { type: 'failedSetup'; reason?: string } | { type: 'fetchingJobStatuses' } | { type: 'fetchedJobStatuses'; @@ -131,7 +131,7 @@ const createStatusReducer = }), {} as Record ), - setupStatus: { type: 'failed', reasons: ['unknown'] }, + setupStatus: { type: 'failed', reasons: action.reason ? [action.reason] : ['unknown'] }, }; } case 'fetchingJobStatuses': { diff --git a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/job_setup_screen.tsx b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/job_setup_screen.tsx index 2de3ee7bbb301..8003c0c9ece1f 100644 --- a/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/job_setup_screen.tsx +++ b/x-pack/plugins/infra/public/pages/metrics/inventory_view/components/ml/anomaly_detection/job_setup_screen.tsx @@ -18,6 +18,8 @@ import { EuiComboBox } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { EuiLoadingSpinner } from '@elastic/eui'; import { useUiTracker } from '@kbn/observability-shared-plugin/public'; +import { EuiCallOut } from '@elastic/eui'; +import { EuiCode } from '@elastic/eui'; import { useSourceContext } from '../../../../../../containers/metrics_source'; import { useMetricK8sModuleContext } from '../../../../../../containers/ml/modules/metrics_k8s/module'; import { useMetricHostsModuleContext } from '../../../../../../containers/ml/modules/metrics_hosts/module'; @@ -191,6 +193,12 @@ export const JobSetupScreen = (props: Props) => { defaultMessage="Something went wrong creating the necessary ML jobs." /> + {setupStatus.reasons.map((errorMessage, i) => ( + + {errorMessage} + + ))} + { ); }; + +const errorCalloutTitle = i18n.translate('xpack.infra.ml.steps.setupProcess.errorCalloutTitle', { + defaultMessage: 'An error occurred', +});