From ae935aa17cb5d77a35676b86fa8916d6159fbcfd Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Tue, 9 Nov 2021 10:49:47 +0000 Subject: [PATCH] [ML] Display warning if clone job fails due to missing data view --- .../jobs/jobs_list/components/utils.js | 15 +++++++++++++- .../ml/anomaly_detection/single_metric_job.ts | 20 +++++++++++++++++++ .../test/functional/services/ml/job_table.ts | 13 ++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js index fe09ed45f1274a..9fcf4bfb0db090 100644 --- a/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js +++ b/x-pack/plugins/ml/public/application/jobs/jobs_list/components/utils.js @@ -220,9 +220,22 @@ export async function cloneJob(jobId) { ]); const dataViewNames = await getDataViewNames(); - const jobIndicesAvailable = dataViewNames.includes(datafeed.indices.join(',')); + const dataViewTitle = datafeed.indices.join(','); + const jobIndicesAvailable = dataViewNames.includes(dataViewTitle); if (jobIndicesAvailable === false) { + const warningText = i18n.translate( + 'xpack.ml.jobsList.managementActions.noSourceDataViewForClone', + { + defaultMessage: + 'Unable to clone the anomaly detection job {jobId}. No data view exists for index {dataViewTitle}.', + values: { jobId, dataViewTitle }, + } + ); + getToastNotifications().addDanger({ + title: warningText, + 'data-test-subj': 'mlCloneJobNoDataViewExistsWarningToast', + }); return; } diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job.ts b/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job.ts index 97b340c0819580..15648086178db8 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job.ts +++ b/x-pack/test/functional/apps/ml/anomaly_detection/single_metric_job.ts @@ -10,6 +10,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const ml = getService('ml'); + const browser = getService('browser'); const jobId = `fq_single_1_${Date.now()}`; const jobIdClone = `${jobId}_clone`; @@ -201,7 +202,26 @@ export default function ({ getService }: FtrProviderContext) { await ml.api.assertDetectorResultsExist(jobId, 0); }); + it('job cloning fails in the single metric wizard if a matching data view does not exist', async () => { + await ml.testExecution.logTestStep('delete data view used by job'); + await ml.testResources.deleteIndexPatternByTitle('ft_farequote'); + + // Refresh page to ensure page has correct cache of data views + await browser.refresh(); + + await ml.testExecution.logTestStep( + 'job cloning clicks the clone action and loads the single metric wizard' + ); + await ml.jobTable.clickCloneJobActionWhenNoDataViewExists(jobId); + }); + it('job cloning opens the existing job in the single metric wizard', async () => { + await ml.testExecution.logTestStep('recreate data view used by job'); + await ml.testResources.createIndexPatternIfNeeded('ft_farequote', '@timestamp'); + + // Refresh page to ensure page has correct cache of data views + await browser.refresh(); + await ml.testExecution.logTestStep( 'job cloning clicks the clone action and loads the single metric wizard' ); diff --git a/x-pack/test/functional/services/ml/job_table.ts b/x-pack/test/functional/services/ml/job_table.ts index 67488d88aa120b..353016afe9ffe0 100644 --- a/x-pack/test/functional/services/ml/job_table.ts +++ b/x-pack/test/functional/services/ml/job_table.ts @@ -373,6 +373,19 @@ export function MachineLearningJobTableProvider( await testSubjects.existOrFail('~mlPageJobWizard'); } + public async clickCloneJobActionWhenNoDataViewExists(jobId: string) { + await this.ensureJobActionsMenuOpen(jobId); + await testSubjects.click('mlActionButtonCloneJob'); + await this.assertNoDataViewForCloneJobWarningToastExist(); + } + + public async assertNoDataViewForCloneJobWarningToastExist() { + await retry.tryForTime(5000, async () => { + const toast = await testSubjects.find('mlCloneJobNoDataViewExistsWarningToast'); + expect(toast).not.to.be(undefined); + }); + } + public async clickEditJobAction(jobId: string) { await this.ensureJobActionsMenuOpen(jobId); await testSubjects.click('mlActionButtonEditJob');