From 7b1fb587aa03cc60754059f3c4f0d10b35afa863 Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Thu, 10 Feb 2022 14:47:26 +0000 Subject: [PATCH] [ML] Add check that forecast results exist --- .../anomaly_detectors/forecast_with_spaces.ts | 18 +++++--- x-pack/test/functional/services/ml/api.ts | 41 +++++++++++++++++++ 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/x-pack/test/api_integration/apis/ml/anomaly_detectors/forecast_with_spaces.ts b/x-pack/test/api_integration/apis/ml/anomaly_detectors/forecast_with_spaces.ts index 7955b0523a24e..19bb3c7a95c55 100644 --- a/x-pack/test/api_integration/apis/ml/anomaly_detectors/forecast_with_spaces.ts +++ b/x-pack/test/api_integration/apis/ml/anomaly_detectors/forecast_with_spaces.ts @@ -17,10 +17,9 @@ export default ({ getService }: FtrProviderContext) => { const spacesService = getService('spaces'); const forecastJobId = 'fq_single_forecast'; + const forecastJobDatafeedId = `datafeed-${forecastJobId}`; const idSpace1 = 'space1'; const idSpace2 = 'space2'; - const jobConfig = ml.commonConfig.getADFqSingleMetricJobConfig(forecastJobId); - const datafeedConfig = ml.commonConfig.getADFqDatafeedConfig(forecastJobId); async function runForecast( jobId: string, @@ -47,6 +46,9 @@ export default ({ getService }: FtrProviderContext) => { await spacesService.create({ id: idSpace1, name: 'space_one', disabledFeatures: [] }); await spacesService.create({ id: idSpace2, name: 'space_two', disabledFeatures: [] }); + const jobConfig = ml.commonConfig.getADFqSingleMetricJobConfig(forecastJobId); + const datafeedConfig = ml.commonConfig.getADFqDatafeedConfig(forecastJobId); + await ml.api.createAnomalyDetectionJob(jobConfig, idSpace1); await ml.api.createDatafeed(datafeedConfig, idSpace1); }); @@ -73,15 +75,19 @@ export default ({ getService }: FtrProviderContext) => { }); it('should run forecast for open job with valid job ID', async () => { - await ml.api.startDatafeed(datafeedConfig.datafeed_id, { start: '0', end: `${Date.now()}` }); - await ml.api.waitForDatafeedState(datafeedConfig.datafeed_id, DATAFEED_STATE.STOPPED); - await ml.api.waitForJobState(jobConfig.job_id, JOB_STATE.CLOSED); + await ml.api.startDatafeed(forecastJobDatafeedId, { start: '0', end: `${Date.now()}` }); + await ml.api.waitForDatafeedState(forecastJobDatafeedId, DATAFEED_STATE.STOPPED); + await ml.api.waitForJobState(forecastJobId, JOB_STATE.CLOSED); await ml.api.openAnomalyDetectionJob(forecastJobId); await runForecast(forecastJobId, idSpace1, '1d', USER.ML_POWERUSER, 200); + await ml.testExecution.logTestStep( + `forecast results should exist for job '${forecastJobId}'` + ); + await ml.api.assertForecastResultsExist(forecastJobId); }); it('should not run forecast for open job with invalid duration', async () => { - await runForecast(forecastJobId, idSpace1, 3600000, USER.ML_VIEWER, 403); + await runForecast(forecastJobId, idSpace1, 3600000, USER.ML_POWERUSER, 400); }); it('should not run forecast for open job with valid job ID as ML Viewer', async () => { diff --git a/x-pack/test/functional/services/ml/api.ts b/x-pack/test/functional/services/ml/api.ts index 58f0b6d678cc2..8d9ba26961940 100644 --- a/x-pack/test/functional/services/ml/api.ts +++ b/x-pack/test/functional/services/ml/api.ts @@ -126,6 +126,47 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { ); }, + async hasForecastResults(jobId: string): Promise { + const body = await es.search({ + index: '.ml-anomalies-*', + body: { + size: 1, + query: { + bool: { + must: [ + { + match: { + job_id: jobId, + }, + }, + { + match: { + result_type: 'model_forecast', + }, + }, + ], + }, + }, + }, + }); + + return body.hits.hits.length > 0; + }, + + async assertForecastResultsExist(jobId: string) { + await retry.waitForWithTimeout( + `forecast results for job ${jobId} to exist`, + 30 * 1000, + async () => { + if ((await this.hasForecastResults(jobId)) === true) { + return true; + } else { + throw new Error(`expected forecast results for job '${jobId}' to exist`); + } + } + ); + }, + async createIndex( indices: string, mappings?: Record | estypes.MappingTypeMapping