mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
Prototype of kibana data scenarios
This commit is contained in:
parent
8eb73eab9f
commit
f1d380c99b
15 changed files with 960 additions and 0 deletions
|
@ -64,6 +64,9 @@ disabled:
|
|||
- x-pack/test/plugin_api_perf/config.js
|
||||
- x-pack/test/screenshot_creation/config.ts
|
||||
- x-pack/test/fleet_packages/config.ts
|
||||
- x-pack/test/api_integration/apis/aiops/data_scenarios/config.ts
|
||||
- x-pack/test/api_integration/apis/ml/data_scenarios/config.ts
|
||||
- x-pack/test/api_integration/apis/transform/data_scenarios/config.ts
|
||||
|
||||
# Scalability testing config that we run in its own pipeline
|
||||
- x-pack/test/scalability/config.ts
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# AIOps Labs API integration tests - Data scenario
|
||||
|
||||
Note the tests in this data_scenarios folder are not intended to run on CI.
|
||||
They need datasets not available within Kibana CI.
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FtrConfigProviderContext } from '@kbn/test';
|
||||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../../config.ts'));
|
||||
|
||||
return {
|
||||
...baseIntegrationTestsConfig.getAll(),
|
||||
testFiles: [require.resolve('.')],
|
||||
};
|
||||
}
|
|
@ -0,0 +1,323 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import fetch from 'node-fetch';
|
||||
import { format as formatUrl } from 'url';
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
|
||||
import { getWindowParameters } from '@kbn/aiops-utils';
|
||||
import type { ApiExplainLogRateSpikes } from '@kbn/aiops-plugin/common/api';
|
||||
|
||||
import type { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
import { parseStream } from './parse_stream';
|
||||
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const supertest = getService('supertest');
|
||||
const config = getService('config');
|
||||
const kibanaServerUrl = formatUrl(config.get('servers.kibana'));
|
||||
|
||||
const clickTime = 1640097150000;
|
||||
const minTime = 1640077200000;
|
||||
const maxTime = 1640112300000;
|
||||
|
||||
const { baselineMin, baselineMax, deviationMin, deviationMax } = getWindowParameters(
|
||||
clickTime,
|
||||
minTime,
|
||||
maxTime
|
||||
);
|
||||
|
||||
const requestBody: ApiExplainLogRateSpikes['body'] = {
|
||||
baselineMax,
|
||||
baselineMin,
|
||||
deviationMax,
|
||||
deviationMin,
|
||||
start: minTime,
|
||||
end: maxTime,
|
||||
index: 'cluster-apm-filebeat-6.8.6-aws-eu-west-1-2021.12.21*',
|
||||
searchQuery: '{"bool":{"filter":[],"must":[{"match_all":{}}],"must_not":[]}}',
|
||||
timeFieldName: '@timestamp',
|
||||
};
|
||||
|
||||
|
||||
const expected = {
|
||||
chunksLength: 179,
|
||||
actionsLength: 178,
|
||||
noIndexChunksLength: 4,
|
||||
noIndexActionsLength: 3,
|
||||
changePointFilter: 'add_change_points',
|
||||
histogramFilter: 'add_change_points_histogram',
|
||||
errorFilter: 'add_error',
|
||||
changePointsLength: 47,
|
||||
changePoints: [
|
||||
{
|
||||
fieldName: 'beat.hostname.keyword',
|
||||
fieldValue: 'ip-172-27-97-204',
|
||||
doc_count: 12631,
|
||||
bg_count: 30175,
|
||||
},
|
||||
{
|
||||
fieldName: 'beat.name.keyword',
|
||||
fieldValue: 'i-0852e3f99b6c512fd',
|
||||
doc_count: 12631,
|
||||
bg_count: 30175,
|
||||
},
|
||||
{
|
||||
fieldName: 'docker.container.id.keyword',
|
||||
fieldValue: 'aa5a7e792e226ccc4f7bbf34dc0e999e17b4f561fd36fbf746365bad5a8112f7',
|
||||
doc_count: 12629,
|
||||
bg_count: 30167,
|
||||
},
|
||||
{
|
||||
fieldName: 'docker.container.id.keyword',
|
||||
fieldValue: 'dc1e531f6598b1f828fc1ccc1939cfc1fceeebd23378fab8f1ba2e8133e53b21',
|
||||
doc_count: 2220,
|
||||
bg_count: 4072,
|
||||
},
|
||||
{
|
||||
fieldName: 'docker.container.image.keyword',
|
||||
fieldValue: 'docker.elastic.co/cloud-assets/apm:7.13.1-0',
|
||||
doc_count: 2222,
|
||||
bg_count: 4126,
|
||||
},
|
||||
{
|
||||
fieldName: 'docker.container.image.keyword',
|
||||
fieldValue: 'docker.elastic.co/cloud-assets/apm:7.9.0-0',
|
||||
doc_count: 1505,
|
||||
bg_count: 2166,
|
||||
},
|
||||
{
|
||||
fieldName: 'docker.container.image.keyword',
|
||||
fieldValue: 'docker.elastic.co/cloud-assets/apm:7.15.2-0',
|
||||
doc_count: 14777,
|
||||
bg_count: 37298,
|
||||
},
|
||||
{
|
||||
fieldName: 'docker.container.labels.co.elastic.cloud.allocator.cluster_id.keyword',
|
||||
fieldValue: 'eb3713439fcd4fdfa60e355f0e57afc0',
|
||||
doc_count: 12629,
|
||||
bg_count: 30167,
|
||||
},
|
||||
{
|
||||
fieldName: 'docker.container.labels.co.elastic.cloud.allocator.cluster_id.keyword',
|
||||
fieldValue: 'ab8b9d3989c54817a1cb4184b2ef6b41',
|
||||
doc_count: 2295,
|
||||
bg_count: 3998,
|
||||
},
|
||||
{
|
||||
fieldName: 'docker.container.labels.co.elastic.cloud.allocator.cluster_id.keyword',
|
||||
fieldValue: '596808a16dec4fc39413bf34b0a70240',
|
||||
doc_count: 1505,
|
||||
bg_count: 2166,
|
||||
},
|
||||
],
|
||||
histogramLength: 20,
|
||||
};
|
||||
|
||||
describe('POST /internal/aiops/explain_log_rate_spikes EXTENDED EXAMPLES', () => {
|
||||
async function requestWithoutStreaming(body: ApiExplainLogRateSpikes['body']) {
|
||||
|
||||
const resp = await supertest
|
||||
.post(`/internal/aiops/explain_log_rate_spikes`)
|
||||
.set('kbn-xsrf', 'kibana')
|
||||
.send(body)
|
||||
.expect(200);
|
||||
|
||||
// compression is on by default so if the request body is undefined
|
||||
// the response header should include "gzip" and otherwise be "undefined"
|
||||
if (body.compressResponse === undefined) {
|
||||
expect(resp.header['content-encoding']).to.be('gzip');
|
||||
} else if (body.compressResponse === false) {
|
||||
expect(resp.header['content-encoding']).to.be(undefined);
|
||||
}
|
||||
|
||||
expect(Buffer.isBuffer(resp.body)).to.be(true);
|
||||
|
||||
const chunks: string[] = resp.body.toString().split('\n');
|
||||
|
||||
expect(chunks.length).to.eql(
|
||||
expected.chunksLength,
|
||||
`Expected 'chunks.length' to be ${expected.chunksLength}, got ${chunks.length}.`
|
||||
);
|
||||
|
||||
const lastChunk = chunks.pop();
|
||||
expect(lastChunk).to.eql('', `Expected 'lastChunk' to be empty string, got '${lastChunk}'.`);
|
||||
|
||||
let data: any[] = [];
|
||||
|
||||
expect(() => {
|
||||
data = chunks.map((c) => JSON.parse(c));
|
||||
}).not.to.throwError();
|
||||
|
||||
|
||||
expect(data.length).to.eql(
|
||||
expected.actionsLength,
|
||||
`Expected 'data.length' to be ${expected.actionsLength}, got ${data.length}.`
|
||||
);
|
||||
data.forEach((d) => {
|
||||
expect(typeof d.type).to.be('string');
|
||||
});
|
||||
|
||||
const addChangePointsActions = data.filter((d) => d.type === expected.changePointFilter);
|
||||
expect(addChangePointsActions.length).to.greaterThan(0);
|
||||
|
||||
const changePoints = addChangePointsActions
|
||||
.flatMap((d) => d.payload)
|
||||
.sort(function (a, b) {
|
||||
if (a.fieldName === b.fieldName) {
|
||||
return b.fieldValue - a.fieldValue;
|
||||
}
|
||||
return a.fieldName > b.fieldName ? 1 : -1;
|
||||
});
|
||||
|
||||
expect(changePoints.length).to.eql(
|
||||
expected.changePointsLength,
|
||||
`Expected 'changePoints.length' to be ${expected.changePointsLength}, got ${changePoints.length}.`
|
||||
);
|
||||
// changePoints.forEach((cp, index) => {
|
||||
// const ecp = expected.changePoints[index];
|
||||
// expect(cp.fieldName).to.equal(ecp.fieldName);
|
||||
// expect(cp.fieldValue).to.equal(ecp.fieldValue);
|
||||
// expect(cp.doc_count).to.equal(ecp.doc_count);
|
||||
// expect(cp.bg_count).to.equal(ecp.bg_count);
|
||||
// });
|
||||
|
||||
const histogramActions = data.filter((d) => d.type === expected.histogramFilter);
|
||||
const histograms = histogramActions.flatMap((d) => d.payload);
|
||||
// for each change point we should get a histogram
|
||||
expect(histogramActions.length).to.be(changePoints.length);
|
||||
// each histogram should have a length of 20 items.
|
||||
histograms.forEach((h, index) => {
|
||||
expect(h.histogram.length).to.be(20);
|
||||
});
|
||||
}
|
||||
|
||||
it('should return full data without streaming with compression with flushFix', async () => {
|
||||
await requestWithoutStreaming(requestBody);
|
||||
});
|
||||
|
||||
it('should return full data without streaming with compression without flushFix', async () => {
|
||||
await requestWithoutStreaming({ ...requestBody, flushFix: false });
|
||||
});
|
||||
|
||||
it('should return full data without streaming without compression with flushFix', async () => {
|
||||
await requestWithoutStreaming({ ...requestBody, compressResponse: false });
|
||||
});
|
||||
|
||||
it('should return full data without streaming without compression without flushFix', async () => {
|
||||
await requestWithoutStreaming({ ...requestBody, compressResponse: false, flushFix: false });
|
||||
});
|
||||
|
||||
async function requestWithStreaming(body: ApiExplainLogRateSpikes['body']) {
|
||||
const resp = await fetch(`${kibanaServerUrl}/internal/aiops/explain_log_rate_spikes`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'kbn-xsrf': 'stream',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
||||
// compression is on by default so if the request body is undefined
|
||||
// the response header should include "gzip" and otherwise be "null"
|
||||
if (body.compressResponse === undefined) {
|
||||
expect(resp.headers.get('content-encoding')).to.be('gzip');
|
||||
} else if (body.compressResponse === false) {
|
||||
expect(resp.headers.get('content-encoding')).to.be(null);
|
||||
}
|
||||
|
||||
expect(resp.ok).to.be(true);
|
||||
expect(resp.status).to.be(200);
|
||||
|
||||
const stream = resp.body;
|
||||
|
||||
expect(stream).not.to.be(null);
|
||||
|
||||
if (stream !== null) {
|
||||
const data: any[] = [];
|
||||
let chunkCounter = 0;
|
||||
const parseStreamCallback = (c: number) => (chunkCounter = c);
|
||||
|
||||
for await (const action of parseStream(stream, parseStreamCallback)) {
|
||||
expect(action.type).not.to.be('error');
|
||||
data.push(action);
|
||||
}
|
||||
|
||||
// If streaming works correctly we should receive more than one chunk.
|
||||
expect(chunkCounter).to.be.greaterThan(1);
|
||||
|
||||
expect(data.length).to.eql(
|
||||
expected.actionsLength,
|
||||
`Expected 'data.length' to be ${expected.actionsLength}, got ${data.length}.`
|
||||
);
|
||||
|
||||
const addChangePointsActions = data.filter((d) => d.type === expected.changePointFilter);
|
||||
expect(addChangePointsActions.length).to.greaterThan(0);
|
||||
|
||||
const changePoints = addChangePointsActions
|
||||
.flatMap((d) => d.payload)
|
||||
.sort(function (a, b) {
|
||||
if (a.fieldName === b.fieldName) {
|
||||
return b.fieldValue - a.fieldValue;
|
||||
}
|
||||
return a.fieldName > b.fieldName ? 1 : -1;
|
||||
});
|
||||
|
||||
expect(changePoints.length).to.eql(
|
||||
expected.changePointsLength,
|
||||
`Expected 'changePoints.length' to be ${expected.changePointsLength}, got ${changePoints.length}.`
|
||||
);
|
||||
// Check only up to 10 changePoints even if there's more
|
||||
changePoints.slice(0, 9).forEach((cp, index) => {
|
||||
const ecp = expected.changePoints.find(
|
||||
(d) => d.fieldName === cp.fieldName && d.fieldValue === cp.fieldValue
|
||||
);
|
||||
expect(ecp).not.to.eql(
|
||||
undefined,
|
||||
`Expected changePoint width 'fieldName:${cp.fieldName}'/'fieldValue:${cp.fieldValue}' to not be undefined`
|
||||
);
|
||||
if (ecp !== undefined) {
|
||||
expect(cp.doc_count).to.eql(
|
||||
ecp.doc_count,
|
||||
`Expected 'doc_count' to be ${ecp.doc_count}, got ${cp.doc_count}.`
|
||||
);
|
||||
expect(cp.bg_count).to.eql(
|
||||
ecp.bg_count,
|
||||
`Expected 'bg_count' to be ${ecp.bg_count}, got ${cp.bg_count}.`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const histogramActions = data.filter((d) => d.type === expected.histogramFilter);
|
||||
const histograms = histogramActions.flatMap((d) => d.payload);
|
||||
// for each change point we should get a histogram
|
||||
expect(histogramActions.length).to.be(changePoints.length);
|
||||
// each histogram should have a length of 20 items.
|
||||
histograms.forEach((h, index) => {
|
||||
expect(h.histogram.length).to.be(20);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
it('should return data in chunks with streaming with compression with flushFix', async () => {
|
||||
await requestWithStreaming(requestBody);
|
||||
});
|
||||
|
||||
it('should return data in chunks with streaming with compression without flushFix', async () => {
|
||||
await requestWithStreaming({ ...requestBody, flushFix: false });
|
||||
});
|
||||
|
||||
it('should return data in chunks with streaming without compression with flushFix', async () => {
|
||||
await requestWithStreaming({ ...requestBody, compressResponse: false });
|
||||
});
|
||||
|
||||
it('should return data in chunks with streaming without compression without flushFix', async () => {
|
||||
await requestWithStreaming({ ...requestBody, compressResponse: false, flushFix: false });
|
||||
});
|
||||
});
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { AIOPS_ENABLED } from '@kbn/aiops-plugin/common';
|
||||
|
||||
import type { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||
describe('AIOps', function () {
|
||||
this.tags(['aiops']);
|
||||
|
||||
if (AIOPS_ENABLED) {
|
||||
loadTestFile(require.resolve('./explain_log_rate_spikes_extended'));
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export async function* parseStream(
|
||||
stream: NodeJS.ReadableStream,
|
||||
callback?: (chunkCounter: number) => void
|
||||
) {
|
||||
let partial = '';
|
||||
let chunkCounter = 0;
|
||||
|
||||
try {
|
||||
for await (const value of stream) {
|
||||
chunkCounter++;
|
||||
const full = `${partial}${value}`;
|
||||
const parts = full.split('\n');
|
||||
const last = parts.pop();
|
||||
|
||||
partial = last ?? '';
|
||||
|
||||
const actions = parts.map((p) => JSON.parse(p));
|
||||
|
||||
for (const action of actions) {
|
||||
yield action;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
yield { type: 'error', payload: error.toString() };
|
||||
}
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback(chunkCounter);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ApiExplainLogRateSpikes } from '@kbn/aiops-plugin/common/api';
|
||||
import type { ChangePoint, ChangePointGroup } from '@kbn/ml-agg-utils';
|
||||
|
||||
export interface TestData {
|
||||
testName: string;
|
||||
esArchive?: string;
|
||||
dataGenerator?: string;
|
||||
requestBody: ApiExplainLogRateSpikes['body'];
|
||||
expected: {
|
||||
chunksLength: number;
|
||||
actionsLength: number;
|
||||
noIndexChunksLength: number;
|
||||
noIndexActionsLength: number;
|
||||
changePointFilter: 'add_change_points';
|
||||
groupFilter: 'add_change_point_group';
|
||||
groupHistogramFilter: 'add_change_point_group_histogram';
|
||||
histogramFilter: 'add_change_points_histogram';
|
||||
errorFilter: 'add_error';
|
||||
changePoints: ChangePoint[];
|
||||
groups: ChangePointGroup[];
|
||||
histogramLength: number;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
# ML API integration tests - Data scenario
|
||||
|
||||
Note the tests in this data_scenarios folder are not intended to run on CI.
|
||||
They need datasets not available within Kibana CI.
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { USER } from '../../../../functional/services/ml/security_common';
|
||||
import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common_api';
|
||||
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const esSupertest = getService('esSupertest');
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const ml = getService('ml');
|
||||
|
||||
const testDataList = [
|
||||
{
|
||||
testTitleSuffix: 'with 1 field, 1 agg, no split',
|
||||
user: USER.ML_POWERUSER,
|
||||
requestBody: {
|
||||
aggTypes: ['sum'],
|
||||
duration: { start: 1325548800000, end: 1538092800000 },
|
||||
fields: ['sale_dollars'],
|
||||
index: 'iowa*',
|
||||
query: { bool: { must: [{ match_all: {} }] } },
|
||||
timeField: 'date',
|
||||
},
|
||||
expected: {
|
||||
responseCode: 200,
|
||||
responseBody: { name: '2d', ms: 172800000 },
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
describe('bucket span estimator', function () {
|
||||
before(async () => {
|
||||
await ml.testResources.setKibanaTimeZoneToUTC();
|
||||
});
|
||||
|
||||
describe('with default settings', function () {
|
||||
for (const testData of testDataList) {
|
||||
it(`estimates the bucket span ${testData.testTitleSuffix}`, async () => {
|
||||
const { body, status } = await supertest
|
||||
.post('/api/ml/validate/estimate_bucket_span')
|
||||
.auth(testData.user, ml.securityCommon.getPasswordForUser(testData.user))
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.send(testData.requestBody);
|
||||
ml.api.assertResponseStatusCode(testData.expected.responseCode, status, body);
|
||||
|
||||
expect(body).to.eql(testData.expected.responseBody);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
17
x-pack/test/api_integration/apis/ml/data_scenarios/config.ts
Normal file
17
x-pack/test/api_integration/apis/ml/data_scenarios/config.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FtrConfigProviderContext } from '@kbn/test';
|
||||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../../config.ts'));
|
||||
|
||||
return {
|
||||
...baseIntegrationTestsConfig.getAll(),
|
||||
testFiles: [require.resolve('.')],
|
||||
};
|
||||
}
|
36
x-pack/test/api_integration/apis/ml/data_scenarios/index.ts
Normal file
36
x-pack/test/api_integration/apis/ml/data_scenarios/index.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default function ({ getService, loadTestFile }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const ml = getService('ml');
|
||||
|
||||
describe('Machine Learning', function () {
|
||||
this.tags(['ml']);
|
||||
|
||||
before(async () => {
|
||||
await ml.securityCommon.createMlRoles();
|
||||
await ml.securityCommon.createMlUsers();
|
||||
|
||||
// ML saved objects (e.g. lang_ident_model_1) might have lost the * space
|
||||
// assignment when privious test suites loaded and unloaded the .kibana index.
|
||||
// We're making sure that it's in the expected state again.
|
||||
await ml.api.initSavedObjects();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await ml.securityCommon.cleanMlUsers();
|
||||
await ml.securityCommon.cleanMlRoles();
|
||||
|
||||
await ml.testResources.resetKibanaTimeZone();
|
||||
});
|
||||
|
||||
loadTestFile(require.resolve('./bucket_span_estimator'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
# Transform API integration tests - Data scenario
|
||||
|
||||
Note the tests in this data_scenarios folder are not intended to run on CI.
|
||||
They need datasets not available within Kibana CI.
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FtrConfigProviderContext } from '@kbn/test';
|
||||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const baseIntegrationTestsConfig = await readConfigFile(require.resolve('../../../config.ts'));
|
||||
|
||||
return {
|
||||
...baseIntegrationTestsConfig.getAll(),
|
||||
testFiles: [require.resolve('.')],
|
||||
};
|
||||
}
|
|
@ -0,0 +1,357 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
|
||||
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common_api';
|
||||
import { USER } from '../../../../functional/services/transform/security_common';
|
||||
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const transform = getService('transform');
|
||||
|
||||
|
||||
const testData = {
|
||||
user: USER.TRANSFORM_POWERUSER,
|
||||
requestBody: {
|
||||
query: { bool: { must: [{ match_all: {} }] } },
|
||||
"fields": [
|
||||
{
|
||||
"fieldName": "bottle_volume_ml",
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"fieldName": "city",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"fieldName": "date",
|
||||
"type": "date"
|
||||
}
|
||||
],
|
||||
"samplerShardSize": 5000,
|
||||
},
|
||||
expected: {
|
||||
responseCode: 200,
|
||||
responseBody: [
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"key": 0,
|
||||
"doc_count": 4971
|
||||
},
|
||||
{
|
||||
"key": 471.05263157894734,
|
||||
"doc_count": 17445
|
||||
},
|
||||
{
|
||||
"key": 942.1052631578947,
|
||||
"doc_count": 5023
|
||||
},
|
||||
{
|
||||
"key": 1413.157894736842,
|
||||
"doc_count": 7174
|
||||
},
|
||||
{
|
||||
"key": 1884.2105263157894,
|
||||
"doc_count": 2
|
||||
},
|
||||
{
|
||||
"key": 2355.2631578947367,
|
||||
"doc_count": 7
|
||||
},
|
||||
{
|
||||
"key": 2826.315789473684,
|
||||
"doc_count": 375
|
||||
},
|
||||
{
|
||||
"key": 3297.368421052631,
|
||||
"doc_count": 0
|
||||
},
|
||||
{
|
||||
"key": 3768.4210526315787,
|
||||
"doc_count": 0
|
||||
},
|
||||
{
|
||||
"key": 4239.473684210526,
|
||||
"doc_count": 0
|
||||
},
|
||||
{
|
||||
"key": 4710.526315789473,
|
||||
"doc_count": 0
|
||||
},
|
||||
{
|
||||
"key": 5181.578947368421,
|
||||
"doc_count": 0
|
||||
},
|
||||
{
|
||||
"key": 5652.631578947368,
|
||||
"doc_count": 2
|
||||
},
|
||||
{
|
||||
"key": 6123.684210526316,
|
||||
"doc_count": 0
|
||||
},
|
||||
{
|
||||
"key": 6594.736842105262,
|
||||
"doc_count": 0
|
||||
},
|
||||
{
|
||||
"key": 7065.78947368421,
|
||||
"doc_count": 0
|
||||
},
|
||||
{
|
||||
"key": 7536.8421052631575,
|
||||
"doc_count": 0
|
||||
},
|
||||
{
|
||||
"key": 8007.894736842105,
|
||||
"doc_count": 0
|
||||
},
|
||||
{
|
||||
"key": 8478.947368421052,
|
||||
"doc_count": 0
|
||||
},
|
||||
{
|
||||
"key": 8950,
|
||||
"doc_count": 1
|
||||
}
|
||||
],
|
||||
"interval": 471.05263157894734,
|
||||
"stats": [
|
||||
50,
|
||||
9000
|
||||
],
|
||||
"type": "numeric",
|
||||
"id": "bottle_volume_ml"
|
||||
},
|
||||
{
|
||||
"type": "ordinal",
|
||||
"cardinality": 378,
|
||||
"data": [
|
||||
{
|
||||
"key": "des moines",
|
||||
"doc_count": 3471
|
||||
},
|
||||
{
|
||||
"key": "cedar rapids",
|
||||
"doc_count": 1907
|
||||
},
|
||||
{
|
||||
"key": "davenport",
|
||||
"doc_count": 1414
|
||||
},
|
||||
{
|
||||
"key": "sioux city",
|
||||
"doc_count": 1347
|
||||
},
|
||||
{
|
||||
"key": "council bluffs",
|
||||
"doc_count": 1184
|
||||
},
|
||||
{
|
||||
"key": "ames",
|
||||
"doc_count": 1147
|
||||
},
|
||||
{
|
||||
"key": "west des moines",
|
||||
"doc_count": 996
|
||||
},
|
||||
{
|
||||
"key": "iowa city",
|
||||
"doc_count": 952
|
||||
},
|
||||
{
|
||||
"key": "waterloo",
|
||||
"doc_count": 880
|
||||
},
|
||||
{
|
||||
"key": "mason city",
|
||||
"doc_count": 748
|
||||
},
|
||||
{
|
||||
"key": "dubuque",
|
||||
"doc_count": 605
|
||||
},
|
||||
{
|
||||
"key": "ankeny",
|
||||
"doc_count": 577
|
||||
},
|
||||
{
|
||||
"key": "cedar falls",
|
||||
"doc_count": 571
|
||||
},
|
||||
{
|
||||
"key": "muscatine",
|
||||
"doc_count": 515
|
||||
},
|
||||
{
|
||||
"key": "coralville",
|
||||
"doc_count": 465
|
||||
},
|
||||
{
|
||||
"key": "marshalltown",
|
||||
"doc_count": 399
|
||||
},
|
||||
{
|
||||
"key": "newton",
|
||||
"doc_count": 378
|
||||
},
|
||||
{
|
||||
"key": "fort dodge",
|
||||
"doc_count": 339
|
||||
},
|
||||
{
|
||||
"key": "urbandale",
|
||||
"doc_count": 337
|
||||
},
|
||||
{
|
||||
"key": "clinton",
|
||||
"doc_count": 313
|
||||
}
|
||||
],
|
||||
"id": "city"
|
||||
},
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"key_as_string": "11/07/2011",
|
||||
"key": 1320692210526.3157,
|
||||
"doc_count": 857
|
||||
},
|
||||
{
|
||||
"key_as_string": "03/08/2012",
|
||||
"key": 1331173894736.842,
|
||||
"doc_count": 1680
|
||||
},
|
||||
{
|
||||
"key_as_string": "07/07/2012",
|
||||
"key": 1341655578947.3684,
|
||||
"doc_count": 1646
|
||||
},
|
||||
{
|
||||
"key_as_string": "11/05/2012",
|
||||
"key": 1352137263157.8948,
|
||||
"doc_count": 1689
|
||||
},
|
||||
{
|
||||
"key_as_string": "03/07/2013",
|
||||
"key": 1362618947368.4211,
|
||||
"doc_count": 1617
|
||||
},
|
||||
{
|
||||
"key_as_string": "07/06/2013",
|
||||
"key": 1373100631578.9473,
|
||||
"doc_count": 1666
|
||||
},
|
||||
{
|
||||
"key_as_string": "11/04/2013",
|
||||
"key": 1383582315789.4736,
|
||||
"doc_count": 1670
|
||||
},
|
||||
{
|
||||
"key_as_string": "03/06/2014",
|
||||
"key": 1394064000000,
|
||||
"doc_count": 1585
|
||||
},
|
||||
{
|
||||
"key_as_string": "07/05/2014",
|
||||
"key": 1404545684210.5264,
|
||||
"doc_count": 1691
|
||||
},
|
||||
{
|
||||
"key_as_string": "11/03/2014",
|
||||
"key": 1415027368421.0527,
|
||||
"doc_count": 1760
|
||||
},
|
||||
{
|
||||
"key_as_string": "03/04/2015",
|
||||
"key": 1425509052631.5789,
|
||||
"doc_count": 1893
|
||||
},
|
||||
{
|
||||
"key_as_string": "07/04/2015",
|
||||
"key": 1435990736842.1052,
|
||||
"doc_count": 1830
|
||||
},
|
||||
{
|
||||
"key_as_string": "11/02/2015",
|
||||
"key": 1446472421052.6316,
|
||||
"doc_count": 1076
|
||||
},
|
||||
{
|
||||
"key_as_string": "03/02/2016",
|
||||
"key": 1456954105263.158,
|
||||
"doc_count": 1981
|
||||
},
|
||||
{
|
||||
"key_as_string": "07/02/2016",
|
||||
"key": 1467435789473.684,
|
||||
"doc_count": 636
|
||||
},
|
||||
{
|
||||
"key_as_string": "10/31/2016",
|
||||
"key": 1477917473684.2104,
|
||||
"doc_count": 6086
|
||||
},
|
||||
{
|
||||
"key_as_string": "03/01/2017",
|
||||
"key": 1488399157894.7368,
|
||||
"doc_count": 159
|
||||
},
|
||||
{
|
||||
"key_as_string": "07/01/2017",
|
||||
"key": 1498880842105.2632,
|
||||
"doc_count": 319
|
||||
},
|
||||
{
|
||||
"key_as_string": "10/30/2017",
|
||||
"key": 1509362526315.7896,
|
||||
"doc_count": 2077
|
||||
},
|
||||
{
|
||||
"key_as_string": "02/28/2018",
|
||||
"key": 1519844210526.3157,
|
||||
"doc_count": 3082
|
||||
}
|
||||
],
|
||||
"interval": 10481684210.526316,
|
||||
"stats": [
|
||||
1325548800000,
|
||||
1524700800000
|
||||
],
|
||||
"type": "numeric",
|
||||
"id": "date"
|
||||
}
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
describe('/api/transform/field_histograms', function () {
|
||||
before(async () => {
|
||||
await transform.testResources.setKibanaTimeZoneToUTC();
|
||||
});
|
||||
|
||||
it('should return a field_histograms', async () => {
|
||||
const { body, status } = await supertest
|
||||
.post('/api/transform/field_histograms/iowa*')
|
||||
.auth(
|
||||
USER.TRANSFORM_POWERUSER,
|
||||
transform.securityCommon.getPasswordForUser(USER.TRANSFORM_POWERUSER)
|
||||
)
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.send(testData.requestBody);
|
||||
transform.api.assertResponseStatusCode(200, status, body);
|
||||
|
||||
expect(body).to.eql(testData.expected.responseBody);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default function ({ getService, loadTestFile }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const transform = getService('transform');
|
||||
|
||||
describe('transform', function () {
|
||||
this.tags(['transform']);
|
||||
|
||||
before(async () => {
|
||||
await transform.securityCommon.createTransformRoles();
|
||||
await transform.securityCommon.createTransformUsers();
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await transform.securityCommon.cleanTransformUsers();
|
||||
await transform.securityCommon.cleanTransformRoles();
|
||||
|
||||
await transform.testResources.resetKibanaTimeZone();
|
||||
});
|
||||
|
||||
loadTestFile(require.resolve('./field_histograms'));
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue