From 3318ecce5f89b6365fbc62ba9c8ec85df79f570c Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Fri, 8 May 2020 15:09:53 -0400 Subject: [PATCH 1/4] wip: create analytics api integration dir --- .../apis/ml/data_frame_analytics/get.ts | 294 ++++++++++++++++++ .../apis/ml/data_frame_analytics/index.ts | 14 + x-pack/test/api_integration/apis/ml/index.ts | 1 + 3 files changed, 309 insertions(+) create mode 100644 x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts create mode 100644 x-pack/test/api_integration/apis/ml/data_frame_analytics/index.ts diff --git a/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts b/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts new file mode 100644 index 0000000000000..72fe30c0e8181 --- /dev/null +++ b/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts @@ -0,0 +1,294 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import expect from '@kbn/expect'; +import { DataFrameAnalyticsConfig } from '../../../../../plugins/ml/public/application/data_frame_analytics/common'; +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { USER } from '../../../../functional/services/machine_learning/security_common'; + +const COMMON_HEADERS = { + 'kbn-xsrf': 'some-xsrf-token', +}; + +export default ({ getService }: FtrProviderContext) => { + const esArchiver = getService('esArchiver'); + const supertest = getService('supertestWithoutAuth'); + const ml = getService('ml'); + + const timestamp = Date.now(); + + async function createJobs() { + const mockJobConfigs: Array<{ + suiteTitle: string; + archive: string; + indexPattern: { name: string; timeField: string }; + job: DataFrameAnalyticsConfig; + }> = [ + { + suiteTitle: 'classification job supported by the form', + archive: 'ml/bm_classification', + indexPattern: { name: 'ft_bank_marketing', timeField: '@timestamp' }, + job: { + id: `bm_1_${timestamp}`, + description: + "Classification job based on 'ft_bank_marketing' dataset with dependentVariable 'y' and trainingPercent '20'", + source: { + index: ['ft_bank_marketing'], + query: { + match_all: {}, + }, + }, + dest: { + index: `user-bm_1_${timestamp}`, + results_field: 'ml', + }, + analysis: { + classification: { + dependent_variable: 'y', + training_percent: 20, + }, + }, + analyzed_fields: { + includes: [], + excludes: [], + }, + model_memory_limit: '350mb', + create_time: 12345, + version: 'version-1', + allow_lazy_start: false, + }, + }, + { + suiteTitle: 'outlier detection job supported by the form', + archive: 'ml/ihp_outlier', + indexPattern: { name: 'ft_ihp_outlier', timeField: '@timestamp' }, + job: { + id: `ihp_1_${timestamp}`, + description: 'This is the job description', + source: { + index: ['ft_ihp_outlier'], + query: { + match_all: {}, + }, + }, + dest: { + index: `user-ihp_1_${timestamp}`, + results_field: 'ml', + }, + analysis: { + outlier_detection: {}, + }, + analyzed_fields: { + includes: [], + excludes: [], + }, + model_memory_limit: '55mb', + create_time: 12345, + version: 'version-1', + allow_lazy_start: false, + }, + }, + { + suiteTitle: 'regression job supported by the form', + archive: 'ml/egs_regression', + indexPattern: { name: 'ft_egs_regression', timeField: '@timestamp' }, + job: { + id: `egs_1_${timestamp}`, + description: 'This is the job description', + source: { + index: ['ft_egs_regression'], + query: { + match_all: {}, + }, + }, + dest: { + index: `user-egs_1_${timestamp}`, + results_field: 'ml', + }, + analysis: { + regression: { + dependent_variable: 'stab', + training_percent: 20, + }, + }, + analyzed_fields: { + includes: [], + excludes: [], + }, + model_memory_limit: '105mb', + create_time: 12345, + version: 'version-1', + allow_lazy_start: false, + }, + }, + ]; + + for (const job of mockJobConfigs) { + await esArchiver.loadIfNeeded(job.archive); + await ml.api.createDataFrameAnalyticsJob(job.job); + } + } + + describe('GET analytics', () => { + before(async () => { + await ml.testResources.setKibanaTimeZoneToUTC(); + await createJobs(); + }); + + after(async () => { + await ml.api.cleanMlIndices(); + }); + + describe('GetAnalytics', () => { + it('should fetch all analytics jobs', async () => { + const { body } = await supertest + .get(`/api/ml/data_frame/analytics`) + .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + .set(COMMON_HEADERS) + .expect(200); + // console.log('------ BODY! ------', JSON.stringify(body, null, 2)); // remove + expect(body.count).to.eql(3); + expect(body.jobs.length).to.eql(3); + // expect(body.jobs[0].job_id).to.eql(`${jobId}_1`); + // expect(body.jobs[1].job_id).to.eql(`${jobId}_2`); + }); + + // it('should not allow to retrieve jobs for the user without required permissions', async () => { + // const { body } = await supertest + // .get(`/api/ml/anomaly_detectors`) + // .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) + // .set(COMMON_HEADERS) + // .expect(404); + + // expect(body.error).to.eql('Not Found'); + // expect(body.message).to.eql('Not Found'); + // }); + }); + + // describe('GetAnomalyDetectorsById', () => { + // it('should fetch single anomaly detector job by id', async () => { + // const { body } = await supertest + // .get(`/api/ml/anomaly_detectors/${jobId}_1`) + // .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + // .set(COMMON_HEADERS) + // .expect(200); + + // expect(body.count).to.eql(1); + // expect(body.jobs.length).to.eql(1); + // expect(body.jobs[0].job_id).to.eql(`${jobId}_1`); + // }); + + // it('should fetch anomaly detector jobs based on provided ids', async () => { + // const { body } = await supertest + // .get(`/api/ml/anomaly_detectors/${jobId}_1,${jobId}_2`) + // .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + // .set(COMMON_HEADERS) + // .expect(200); + + // expect(body.count).to.eql(2); + // expect(body.jobs.length).to.eql(2); + // expect(body.jobs[0].job_id).to.eql(`${jobId}_1`); + // expect(body.jobs[1].job_id).to.eql(`${jobId}_2`); + // }); + + // it('should not allow to retrieve a job for the user without required permissions', async () => { + // const { body } = await supertest + // .get(`/api/ml/anomaly_detectors/${jobId}_1`) + // .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) + // .set(COMMON_HEADERS) + // .expect(404); + + // expect(body.error).to.eql('Not Found'); + // expect(body.message).to.eql('Not Found'); + // }); + // }); + + // describe('GetAnomalyDetectorsStats', () => { + // it('should fetch jobs stats', async () => { + // const { body } = await supertest + // .get(`/api/ml/anomaly_detectors/_stats`) + // .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + // .set(COMMON_HEADERS) + // .expect(200); + + // expect(body.count).to.eql(2); + // expect(body.jobs.length).to.eql(2); + // expect(body.jobs[0].job_id).to.eql(`${jobId}_1`); + // expect(body.jobs[0]).to.keys( + // 'timing_stats', + // 'state', + // 'forecasts_stats', + // 'model_size_stats', + // 'data_counts' + // ); + // expect(body.jobs[1].job_id).to.eql(`${jobId}_2`); + // }); + + // it('should not allow to retrieve jobs stats for the user without required permissions', async () => { + // const { body } = await supertest + // .get(`/api/ml/anomaly_detectors/_stats`) + // .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) + // .set(COMMON_HEADERS) + // .expect(404); + + // expect(body.error).to.eql('Not Found'); + // expect(body.message).to.eql('Not Found'); + // }); + // }); + + // describe('GetAnomalyDetectorsStatsById', () => { + // it('should fetch single job stats', async () => { + // const { body } = await supertest + // .get(`/api/ml/anomaly_detectors/${jobId}_1/_stats`) + // .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + // .set(COMMON_HEADERS) + // .expect(200); + + // expect(body.count).to.eql(1); + // expect(body.jobs.length).to.eql(1); + // expect(body.jobs[0].job_id).to.eql(`${jobId}_1`); + // expect(body.jobs[0]).to.keys( + // 'timing_stats', + // 'state', + // 'forecasts_stats', + // 'model_size_stats', + // 'data_counts' + // ); + // }); + + // it('should fetch multiple jobs stats based on provided ids', async () => { + // const { body } = await supertest + // .get(`/api/ml/anomaly_detectors/${jobId}_1,${jobId}_2/_stats`) + // .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + // .set(COMMON_HEADERS) + // .expect(200); + + // expect(body.count).to.eql(2); + // expect(body.jobs.length).to.eql(2); + // expect(body.jobs[0].job_id).to.eql(`${jobId}_1`); + // expect(body.jobs[0]).to.keys( + // 'timing_stats', + // 'state', + // 'forecasts_stats', + // 'model_size_stats', + // 'data_counts' + // ); + // expect(body.jobs[1].job_id).to.eql(`${jobId}_2`); + // }); + + // it('should not allow to retrieve a job stats for the user without required permissions', async () => { + // const { body } = await supertest + // .get(`/api/ml/anomaly_detectors/${jobId}_1/_stats`) + // .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) + // .set(COMMON_HEADERS) + // .expect(404); + + // expect(body.error).to.eql('Not Found'); + // expect(body.message).to.eql('Not Found'); + // }); + // }); + }); +}; diff --git a/x-pack/test/api_integration/apis/ml/data_frame_analytics/index.ts b/x-pack/test/api_integration/apis/ml/data_frame_analytics/index.ts new file mode 100644 index 0000000000000..a9a0b2022724f --- /dev/null +++ b/x-pack/test/api_integration/apis/ml/data_frame_analytics/index.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function({ loadTestFile }: FtrProviderContext) { + describe('data frame analytics', function() { + loadTestFile(require.resolve('./get')); + // loadTestFile(require.resolve('./get_overall_stats')); + }); +} diff --git a/x-pack/test/api_integration/apis/ml/index.ts b/x-pack/test/api_integration/apis/ml/index.ts index df99b125e6adb..afe3106906041 100644 --- a/x-pack/test/api_integration/apis/ml/index.ts +++ b/x-pack/test/api_integration/apis/ml/index.ts @@ -38,5 +38,6 @@ export default function({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./job_validation')); loadTestFile(require.resolve('./jobs')); loadTestFile(require.resolve('./results')); + loadTestFile(require.resolve('./data_frame_analytics')); }); } From ab222c77d66036a6c585672261f05586fc240ea5 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Mon, 11 May 2020 18:15:39 -0400 Subject: [PATCH 2/4] add get analytics tests --- .../apis/ml/data_frame_analytics/get.ts | 392 ++++++++---------- .../apis/ml/data_frame_analytics/index.ts | 1 - 2 files changed, 169 insertions(+), 224 deletions(-) diff --git a/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts b/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts index 72fe30c0e8181..8984d8cd9ad1a 100644 --- a/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts +++ b/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts @@ -5,7 +5,6 @@ */ import expect from '@kbn/expect'; -import { DataFrameAnalyticsConfig } from '../../../../../plugins/ml/public/application/data_frame_analytics/common'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { USER } from '../../../../functional/services/machine_learning/security_common'; @@ -18,123 +17,74 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertestWithoutAuth'); const ml = getService('ml'); - const timestamp = Date.now(); + const jobId = `bm_${Date.now()}`; async function createJobs() { - const mockJobConfigs: Array<{ - suiteTitle: string; - archive: string; - indexPattern: { name: string; timeField: string }; - job: DataFrameAnalyticsConfig; - }> = [ + const mockJobConfigs = [ { - suiteTitle: 'classification job supported by the form', - archive: 'ml/bm_classification', - indexPattern: { name: 'ft_bank_marketing', timeField: '@timestamp' }, - job: { - id: `bm_1_${timestamp}`, - description: - "Classification job based on 'ft_bank_marketing' dataset with dependentVariable 'y' and trainingPercent '20'", - source: { - index: ['ft_bank_marketing'], - query: { - match_all: {}, - }, + id: `${jobId}_1`, + description: + "Classification job based on 'ft_bank_marketing' dataset with dependentVariable 'y' and trainingPercent '20'", + source: { + index: ['ft_bank_marketing'], + query: { + match_all: {}, }, - dest: { - index: `user-bm_1_${timestamp}`, - results_field: 'ml', - }, - analysis: { - classification: { - dependent_variable: 'y', - training_percent: 20, - }, - }, - analyzed_fields: { - includes: [], - excludes: [], - }, - model_memory_limit: '350mb', - create_time: 12345, - version: 'version-1', - allow_lazy_start: false, }, - }, - { - suiteTitle: 'outlier detection job supported by the form', - archive: 'ml/ihp_outlier', - indexPattern: { name: 'ft_ihp_outlier', timeField: '@timestamp' }, - job: { - id: `ihp_1_${timestamp}`, - description: 'This is the job description', - source: { - index: ['ft_ihp_outlier'], - query: { - match_all: {}, - }, - }, - dest: { - index: `user-ihp_1_${timestamp}`, - results_field: 'ml', - }, - analysis: { - outlier_detection: {}, - }, - analyzed_fields: { - includes: [], - excludes: [], + dest: { + index: `user-bm_${jobId}_1`, + results_field: 'ml', + }, + analysis: { + classification: { + dependent_variable: 'y', + training_percent: 20, }, - model_memory_limit: '55mb', - create_time: 12345, - version: 'version-1', - allow_lazy_start: false, }, + analyzed_fields: { + includes: [], + excludes: [], + }, + model_memory_limit: '350mb', }, { - suiteTitle: 'regression job supported by the form', - archive: 'ml/egs_regression', - indexPattern: { name: 'ft_egs_regression', timeField: '@timestamp' }, - job: { - id: `egs_1_${timestamp}`, - description: 'This is the job description', - source: { - index: ['ft_egs_regression'], - query: { - match_all: {}, - }, - }, - dest: { - index: `user-egs_1_${timestamp}`, - results_field: 'ml', - }, - analysis: { - regression: { - dependent_variable: 'stab', - training_percent: 20, - }, + id: `${jobId}_2`, + description: + "Regression job based on 'ft_bank_marketing' dataset with dependentVariable 'duration' and trainingPercent '20'", + source: { + index: ['ft_bank_marketing'], + query: { + match_all: {}, }, - analyzed_fields: { - includes: [], - excludes: [], + }, + dest: { + index: `user-bm_${jobId}_2`, + results_field: 'ml', + }, + analysis: { + regression: { + dependent_variable: 'duration', + training_percent: 20, }, - model_memory_limit: '105mb', - create_time: 12345, - version: 'version-1', - allow_lazy_start: false, }, + analyzed_fields: { + includes: [], + excludes: [], + }, + model_memory_limit: '350mb', }, ]; - for (const job of mockJobConfigs) { - await esArchiver.loadIfNeeded(job.archive); - await ml.api.createDataFrameAnalyticsJob(job.job); + for (const jobConfig of mockJobConfigs) { + await ml.api.createDataFrameAnalyticsJob(jobConfig); } } - describe('GET analytics', () => { + describe('GetDataFrameAnalytics', () => { before(async () => { + await esArchiver.loadIfNeeded('ml/bm_classification'); await ml.testResources.setKibanaTimeZoneToUTC(); + await createJobs(); }); @@ -142,153 +92,149 @@ export default ({ getService }: FtrProviderContext) => { await ml.api.cleanMlIndices(); }); - describe('GetAnalytics', () => { + describe('GetDataFrameAnalytics', () => { it('should fetch all analytics jobs', async () => { const { body } = await supertest .get(`/api/ml/data_frame/analytics`) .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) .set(COMMON_HEADERS) .expect(200); - // console.log('------ BODY! ------', JSON.stringify(body, null, 2)); // remove - expect(body.count).to.eql(3); - expect(body.jobs.length).to.eql(3); - // expect(body.jobs[0].job_id).to.eql(`${jobId}_1`); - // expect(body.jobs[1].job_id).to.eql(`${jobId}_2`); + expect(body.count).to.eql(2); + expect(body.data_frame_analytics.length).to.eql(2); + expect(body.data_frame_analytics[0].id).to.eql(`${jobId}_1`); + expect(body.data_frame_analytics[1].id).to.eql(`${jobId}_2`); }); - // it('should not allow to retrieve jobs for the user without required permissions', async () => { - // const { body } = await supertest - // .get(`/api/ml/anomaly_detectors`) - // .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) - // .set(COMMON_HEADERS) - // .expect(404); + it('should not allow to retrieve analytics jobs for the user without required permissions', async () => { + const { body } = await supertest + .get(`/api/ml/data_frame/analytics`) + .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) + .set(COMMON_HEADERS) + .expect(404); - // expect(body.error).to.eql('Not Found'); - // expect(body.message).to.eql('Not Found'); - // }); + expect(body.error).to.eql('Not Found'); + expect(body.message).to.eql('Not Found'); + }); }); - // describe('GetAnomalyDetectorsById', () => { - // it('should fetch single anomaly detector job by id', async () => { - // const { body } = await supertest - // .get(`/api/ml/anomaly_detectors/${jobId}_1`) - // .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) - // .set(COMMON_HEADERS) - // .expect(200); - - // expect(body.count).to.eql(1); - // expect(body.jobs.length).to.eql(1); - // expect(body.jobs[0].job_id).to.eql(`${jobId}_1`); - // }); - - // it('should fetch anomaly detector jobs based on provided ids', async () => { - // const { body } = await supertest - // .get(`/api/ml/anomaly_detectors/${jobId}_1,${jobId}_2`) - // .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) - // .set(COMMON_HEADERS) - // .expect(200); - - // expect(body.count).to.eql(2); - // expect(body.jobs.length).to.eql(2); - // expect(body.jobs[0].job_id).to.eql(`${jobId}_1`); - // expect(body.jobs[1].job_id).to.eql(`${jobId}_2`); - // }); + describe('GetDataFrameAnalyticsById', () => { + it('should fetch single analytics job by id', async () => { + const { body } = await supertest + .get(`/api/ml/data_frame/analytics/${jobId}_1`) + .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + .set(COMMON_HEADERS) + .expect(200); - // it('should not allow to retrieve a job for the user without required permissions', async () => { - // const { body } = await supertest - // .get(`/api/ml/anomaly_detectors/${jobId}_1`) - // .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) - // .set(COMMON_HEADERS) - // .expect(404); + expect(body.count).to.eql(1); + expect(body.data_frame_analytics.length).to.eql(1); + expect(body.data_frame_analytics[0].id).to.eql(`${jobId}_1`); + }); - // expect(body.error).to.eql('Not Found'); - // expect(body.message).to.eql('Not Found'); - // }); - // }); + it('should fetch analytics jobs based on provided ids', async () => { + const { body } = await supertest + .get(`/api/ml/data_frame/analytics/${jobId}_1,${jobId}_2`) + .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + .set(COMMON_HEADERS) + .expect(200); - // describe('GetAnomalyDetectorsStats', () => { - // it('should fetch jobs stats', async () => { - // const { body } = await supertest - // .get(`/api/ml/anomaly_detectors/_stats`) - // .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) - // .set(COMMON_HEADERS) - // .expect(200); + expect(body.count).to.eql(2); + expect(body.data_frame_analytics.length).to.eql(2); + expect(body.data_frame_analytics[0].id).to.eql(`${jobId}_1`); + expect(body.data_frame_analytics[1].id).to.eql(`${jobId}_2`); + }); - // expect(body.count).to.eql(2); - // expect(body.jobs.length).to.eql(2); - // expect(body.jobs[0].job_id).to.eql(`${jobId}_1`); - // expect(body.jobs[0]).to.keys( - // 'timing_stats', - // 'state', - // 'forecasts_stats', - // 'model_size_stats', - // 'data_counts' - // ); - // expect(body.jobs[1].job_id).to.eql(`${jobId}_2`); - // }); + it('should not allow to retrieve a job for the user without required permissions', async () => { + const { body } = await supertest + .get(`/api/ml/data_frame/analytics/${jobId}_1`) + .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) + .set(COMMON_HEADERS) + .expect(404); - // it('should not allow to retrieve jobs stats for the user without required permissions', async () => { - // const { body } = await supertest - // .get(`/api/ml/anomaly_detectors/_stats`) - // .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) - // .set(COMMON_HEADERS) - // .expect(404); + expect(body.error).to.eql('Not Found'); + expect(body.message).to.eql('Not Found'); + }); + }); - // expect(body.error).to.eql('Not Found'); - // expect(body.message).to.eql('Not Found'); - // }); - // }); + describe('GetDataFrameAnalyticsStats', () => { + it('should fetch analytics jobs stats', async () => { + const { body } = await supertest + .get(`/api/ml/data_frame/analytics/_stats`) + .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + .set(COMMON_HEADERS) + .expect(200); - // describe('GetAnomalyDetectorsStatsById', () => { - // it('should fetch single job stats', async () => { - // const { body } = await supertest - // .get(`/api/ml/anomaly_detectors/${jobId}_1/_stats`) - // .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) - // .set(COMMON_HEADERS) - // .expect(200); + expect(body.count).to.eql(2); + expect(body.data_frame_analytics.length).to.eql(2); + expect(body.data_frame_analytics[0].id).to.eql(`${jobId}_1`); + expect(body.data_frame_analytics[0]).to.keys( + 'id', + 'state', + 'progress', + 'data_counts', + 'memory_usage' + ); + expect(body.data_frame_analytics[1].id).to.eql(`${jobId}_2`); + }); - // expect(body.count).to.eql(1); - // expect(body.jobs.length).to.eql(1); - // expect(body.jobs[0].job_id).to.eql(`${jobId}_1`); - // expect(body.jobs[0]).to.keys( - // 'timing_stats', - // 'state', - // 'forecasts_stats', - // 'model_size_stats', - // 'data_counts' - // ); - // }); + it('should not allow to retrieve jobs stats for the user without required permissions', async () => { + const { body } = await supertest + .get(`/api/ml/data_frame/analytics/_stats`) + .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) + .set(COMMON_HEADERS) + .expect(404); - // it('should fetch multiple jobs stats based on provided ids', async () => { - // const { body } = await supertest - // .get(`/api/ml/anomaly_detectors/${jobId}_1,${jobId}_2/_stats`) - // .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) - // .set(COMMON_HEADERS) - // .expect(200); + expect(body.error).to.eql('Not Found'); + expect(body.message).to.eql('Not Found'); + }); + }); - // expect(body.count).to.eql(2); - // expect(body.jobs.length).to.eql(2); - // expect(body.jobs[0].job_id).to.eql(`${jobId}_1`); - // expect(body.jobs[0]).to.keys( - // 'timing_stats', - // 'state', - // 'forecasts_stats', - // 'model_size_stats', - // 'data_counts' - // ); - // expect(body.jobs[1].job_id).to.eql(`${jobId}_2`); - // }); + describe('GetDataFrameAnalyticsStatsById', () => { + it('should fetch analytics job stats', async () => { + const { body } = await supertest + .get(`/api/ml/data_frame/analytics/${jobId}_1/_stats`) + .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + .set(COMMON_HEADERS) + .expect(200); + expect(body.count).to.eql(1); + expect(body.data_frame_analytics.length).to.eql(1); + expect(body.data_frame_analytics[0].id).to.eql(`${jobId}_1`); + expect(body.data_frame_analytics[0]).to.keys( + 'id', + 'state', + 'progress', + 'data_counts', + 'memory_usage' + ); + }); - // it('should not allow to retrieve a job stats for the user without required permissions', async () => { - // const { body } = await supertest - // .get(`/api/ml/anomaly_detectors/${jobId}_1/_stats`) - // .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) - // .set(COMMON_HEADERS) - // .expect(404); + it('should fetch multiple analytics jobs stats based on provided ids', async () => { + const { body } = await supertest + .get(`/api/ml/data_frame/analytics/${jobId}_1,${jobId}_2/_stats`) + .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) + .set(COMMON_HEADERS) + .expect(200); + expect(body.count).to.eql(2); + expect(body.data_frame_analytics.length).to.eql(2); + expect(body.data_frame_analytics[0].id).to.eql(`${jobId}_1`); + expect(body.data_frame_analytics[0]).to.keys( + 'id', + 'state', + 'progress', + 'data_counts', + 'memory_usage' + ); + expect(body.data_frame_analytics[1].id).to.eql(`${jobId}_2`); + }); - // expect(body.error).to.eql('Not Found'); - // expect(body.message).to.eql('Not Found'); - // }); - // }); + it('should not allow to retrieve a job stats for the user without required permissions', async () => { + const { body } = await supertest + .get(`/api/ml/data_frame/analytics/${jobId}_1/_stats`) + .auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED)) + .set(COMMON_HEADERS) + .expect(404); + expect(body.error).to.eql('Not Found'); + expect(body.message).to.eql('Not Found'); + }); + }); }); }; diff --git a/x-pack/test/api_integration/apis/ml/data_frame_analytics/index.ts b/x-pack/test/api_integration/apis/ml/data_frame_analytics/index.ts index a9a0b2022724f..b79d2d2005e45 100644 --- a/x-pack/test/api_integration/apis/ml/data_frame_analytics/index.ts +++ b/x-pack/test/api_integration/apis/ml/data_frame_analytics/index.ts @@ -9,6 +9,5 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function({ loadTestFile }: FtrProviderContext) { describe('data frame analytics', function() { loadTestFile(require.resolve('./get')); - // loadTestFile(require.resolve('./get_overall_stats')); }); } From 2d6a82732ea98cfd50ddb77bb3c09ee29ca6bb63 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Tue, 12 May 2020 10:36:57 -0400 Subject: [PATCH 3/4] update types and naming --- .../apis/ml/data_frame_analytics/get.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts b/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts index 8984d8cd9ad1a..0083250beed74 100644 --- a/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts +++ b/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts @@ -7,6 +7,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { USER } from '../../../../functional/services/machine_learning/security_common'; +import { DataFrameAnalyticsConfig } from '../../../../../plugins/ml/public/application/data_frame_analytics/common'; const COMMON_HEADERS = { 'kbn-xsrf': 'some-xsrf-token', @@ -32,7 +33,7 @@ export default ({ getService }: FtrProviderContext) => { }, }, dest: { - index: `user-bm_${jobId}_1`, + index: `user-${jobId}_1`, results_field: 'ml', }, analysis: { @@ -58,7 +59,7 @@ export default ({ getService }: FtrProviderContext) => { }, }, dest: { - index: `user-bm_${jobId}_2`, + index: `user-${jobId}_2`, results_field: 'ml', }, analysis: { @@ -76,11 +77,11 @@ export default ({ getService }: FtrProviderContext) => { ]; for (const jobConfig of mockJobConfigs) { - await ml.api.createDataFrameAnalyticsJob(jobConfig); + await ml.api.createDataFrameAnalyticsJob(jobConfig as DataFrameAnalyticsConfig); } } - describe('GetDataFrameAnalytics', () => { + describe('GET data_frame/analytics', () => { before(async () => { await esArchiver.loadIfNeeded('ml/bm_classification'); await ml.testResources.setKibanaTimeZoneToUTC(); @@ -166,7 +167,7 @@ export default ({ getService }: FtrProviderContext) => { expect(body.count).to.eql(2); expect(body.data_frame_analytics.length).to.eql(2); expect(body.data_frame_analytics[0].id).to.eql(`${jobId}_1`); - expect(body.data_frame_analytics[0]).to.keys( + expect(body.data_frame_analytics[0]).to.have.keys( 'id', 'state', 'progress', @@ -189,7 +190,7 @@ export default ({ getService }: FtrProviderContext) => { }); describe('GetDataFrameAnalyticsStatsById', () => { - it('should fetch analytics job stats', async () => { + it('should fetch single analytics job stats by id', async () => { const { body } = await supertest .get(`/api/ml/data_frame/analytics/${jobId}_1/_stats`) .auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER)) @@ -198,7 +199,7 @@ export default ({ getService }: FtrProviderContext) => { expect(body.count).to.eql(1); expect(body.data_frame_analytics.length).to.eql(1); expect(body.data_frame_analytics[0].id).to.eql(`${jobId}_1`); - expect(body.data_frame_analytics[0]).to.keys( + expect(body.data_frame_analytics[0]).to.have.keys( 'id', 'state', 'progress', @@ -216,7 +217,7 @@ export default ({ getService }: FtrProviderContext) => { expect(body.count).to.eql(2); expect(body.data_frame_analytics.length).to.eql(2); expect(body.data_frame_analytics[0].id).to.eql(`${jobId}_1`); - expect(body.data_frame_analytics[0]).to.keys( + expect(body.data_frame_analytics[0]).to.have.keys( 'id', 'state', 'progress', From f7fe222753ca291b27bcd415052a928ac312cab4 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Tue, 12 May 2020 14:08:54 -0400 Subject: [PATCH 4/4] update api test types --- .../test/api_integration/apis/ml/data_frame_analytics/get.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts b/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts index 0083250beed74..0ee99d9931f39 100644 --- a/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts +++ b/x-pack/test/api_integration/apis/ml/data_frame_analytics/get.ts @@ -8,6 +8,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { USER } from '../../../../functional/services/machine_learning/security_common'; import { DataFrameAnalyticsConfig } from '../../../../../plugins/ml/public/application/data_frame_analytics/common'; +import { DeepPartial } from '../../../../../plugins/ml/common/types/common'; const COMMON_HEADERS = { 'kbn-xsrf': 'some-xsrf-token', @@ -21,7 +22,7 @@ export default ({ getService }: FtrProviderContext) => { const jobId = `bm_${Date.now()}`; async function createJobs() { - const mockJobConfigs = [ + const mockJobConfigs: Array> = [ { id: `${jobId}_1`, description: