diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index 64ebc0efb1252..b5a810852b94d 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -436,10 +436,8 @@ using the CURL scripts in the scripts folder. |{kib-repo}blob/{branch}/x-pack/plugins/ml/readme.md[ml] -|To use machine learning features, you must have a Platinum or Enterprise license -or a free 14-day trial. File Data Visualizer requires a Basic license. For more -info, refer to -Set up machine learning features. +|This plugin provides access to the machine learning features provided by +Elastic. |{kib-repo}blob/{branch}/x-pack/plugins/monitoring[monitoring] diff --git a/x-pack/plugins/ml/readme.md b/x-pack/plugins/ml/readme.md index 97db7ce22e1ad..0e50867e57ad6 100644 --- a/x-pack/plugins/ml/readme.md +++ b/x-pack/plugins/ml/readme.md @@ -1,5 +1,8 @@ # Documentation for ML UI developers +This plugin provides access to the machine learning features provided by +Elastic. + ## Requirements To use machine learning features, you must have a Platinum or Enterprise license diff --git a/x-pack/test/api_integration/apis/ml/job_validation/cardinality.ts b/x-pack/test/api_integration/apis/ml/job_validation/cardinality.ts index 00c1ae12e182a..f7657e482d87d 100644 --- a/x-pack/test/api_integration/apis/ml/job_validation/cardinality.ts +++ b/x-pack/test/api_integration/apis/ml/job_validation/cardinality.ts @@ -13,6 +13,8 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertestWithoutAuth'); const ml = getService('ml'); + const VALIDATED_SEPARATELY = 'this value is not validated directly'; + describe('ValidateCardinality', function () { before(async () => { await esArchiver.loadIfNeeded('ml/ecommerce'); @@ -60,9 +62,7 @@ export default ({ getService }: FtrProviderContext) => { expect(body).to.eql([{ id: 'success_cardinality' }]); }); - // Failing ES promotion due to changes in the cardinality agg, - // see https://github.com/elastic/kibana/issues/80418 - it.skip(`should recognize a high model plot cardinality`, async () => { + it(`should recognize a high model plot cardinality`, async () => { const requestBody = { job_id: '', description: '', @@ -96,10 +96,32 @@ export default ({ getService }: FtrProviderContext) => { .send(requestBody) .expect(200); - expect(body).to.eql([ - { id: 'cardinality_model_plot_high', modelPlotCardinality: 4711 }, + const expectedResponse = [ + { + id: 'cardinality_model_plot_high', + modelPlotCardinality: VALIDATED_SEPARATELY, + }, { id: 'cardinality_partition_field', fieldName: 'order_id' }, - ]); + ]; + + expect(body.length).to.eql( + expectedResponse.length, + `Response body should have ${expectedResponse.length} entries (got ${body})` + ); + for (const entry of expectedResponse) { + const responseEntry = body.find((obj: any) => obj.id === entry.id); + expect(responseEntry).to.not.eql( + undefined, + `Response entry with id '${entry.id}' should exist` + ); + + if (entry.id === 'cardinality_model_plot_high') { + // don't check the exact value of modelPlotCardinality as this is an approximation + expect(responseEntry).to.have.property('modelPlotCardinality'); + } else { + expect(responseEntry).to.eql(entry); + } + } }); it('should not validate cardinality in case request payload is invalid', async () => { diff --git a/x-pack/test/api_integration/apis/ml/job_validation/validate.ts b/x-pack/test/api_integration/apis/ml/job_validation/validate.ts index 01e3da64a515d..8f78cdf015601 100644 --- a/x-pack/test/api_integration/apis/ml/job_validation/validate.ts +++ b/x-pack/test/api_integration/apis/ml/job_validation/validate.ts @@ -14,6 +14,8 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertestWithoutAuth'); const ml = getService('ml'); + const VALIDATED_SEPARATELY = 'this value is not validated directly'; + describe('Validate job', function () { before(async () => { await esArchiver.loadIfNeeded('ml/ecommerce'); @@ -178,9 +180,7 @@ export default ({ getService }: FtrProviderContext) => { ]); }); - // Failing ES promotion due to changes in the cardinality agg, - // see https://github.com/elastic/kibana/issues/80418 - it.skip('should recognize non-basic issues in job configuration', async () => { + it('should recognize non-basic issues in job configuration', async () => { const requestBody = { duration: { start: 1586995459000, end: 1589672736000 }, job: { @@ -236,7 +236,7 @@ export default ({ getService }: FtrProviderContext) => { } }); - expect(body).to.eql([ + const expectedResponse = [ { id: 'job_id_valid', heading: 'Job ID format is valid', @@ -254,10 +254,9 @@ export default ({ getService }: FtrProviderContext) => { }, { id: 'cardinality_model_plot_high', - modelPlotCardinality: 4711, - text: - 'The estimated cardinality of 4711 of fields relevant to creating model plots might result in resource intensive jobs.', - status: 'warning', + modelPlotCardinality: VALIDATED_SEPARATELY, + text: VALIDATED_SEPARATELY, + status: VALIDATED_SEPARATELY, }, { id: 'cardinality_partition_field', @@ -298,7 +297,32 @@ export default ({ getService }: FtrProviderContext) => { url: `https://www.elastic.co/guide/en/machine-learning/${pkg.branch}/create-jobs.html#model-memory-limits`, status: 'warning', }, - ]); + ]; + + expect(body.length).to.eql( + expectedResponse.length, + `Response body should have ${expectedResponse.length} entries (got ${body})` + ); + for (const entry of expectedResponse) { + const responseEntry = body.find((obj: any) => obj.id === entry.id); + expect(responseEntry).to.not.eql( + undefined, + `Response entry with id '${entry.id}' should exist` + ); + + if (entry.id === 'cardinality_model_plot_high') { + // don't check the exact value of modelPlotCardinality as this is an approximation + expect(responseEntry).to.have.property('modelPlotCardinality'); + expect(responseEntry) + .to.have.property('text') + .match( + /^The estimated cardinality of [0-9]+ of fields relevant to creating model plots might result in resource intensive jobs./ + ); + expect(responseEntry).to.have.property('status', 'warning'); + } else { + expect(responseEntry).to.eql(entry); + } + } }); it('should not validate configuration in case request payload is invalid', async () => {