[ML] Transform functional tests - bootstrap transform job for clone test (#57992)

This PR adds transform bootstrapping to the functional test transform.api service and demonstrates the usage in a new cloning test file, which will be completed as part of the transform cloning PR.
This commit is contained in:
Robert Oskamp 2020-02-20 13:31:04 +01:00 committed by GitHub
parent b07aa09606
commit 16eb81628f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 157 additions and 0 deletions

View file

@ -0,0 +1,65 @@
/*
* 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';
import { TransformPivotConfig } from '../../../../legacy/plugins/transform/public/app/common';
function getTransformConfig(): TransformPivotConfig {
const date = Date.now();
return {
id: `ec_2_${date}`,
source: { index: ['ecommerce'] },
pivot: {
group_by: { category: { terms: { field: 'category.keyword' } } },
aggregations: { 'products.base_price.avg': { avg: { field: 'products.base_price' } } },
},
description:
'ecommerce batch transform with avg(products.base_price) grouped by terms(category.keyword)',
dest: { index: `user-ec_2_${date}` },
};
}
export default function({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const transform = getService('transform');
describe('cloning', function() {
this.tags(['smoke']);
const transformConfig = getTransformConfig();
before(async () => {
await esArchiver.load('ml/ecommerce');
await transform.api.createAndRunTransform(transformConfig);
await transform.securityUI.loginAsTransformPowerUser();
});
after(async () => {
await esArchiver.unload('ml/ecommerce');
await transform.api.deleteIndices(transformConfig.dest.index);
await transform.api.cleanTransformIndices();
});
const testDataList = [
{
suiteTitle: 'batch transform with terms group and avg agg',
expected: {},
},
];
for (const testData of testDataList) {
describe(`${testData.suiteTitle}`, function() {
after(async () => {
// await transform.api.deleteIndices(<CLONE_DEST_INDEX>);
});
it('loads the home page', async () => {
await transform.navigation.navigateTo();
await transform.management.assertTransformListPageExists();
});
});
}
});
}

View file

@ -23,5 +23,6 @@ export default function({ getService, loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./creation_index_pattern'));
loadTestFile(require.resolve('./creation_saved_search'));
loadTestFile(require.resolve('./cloning'));
});
}

View file

@ -7,10 +7,17 @@ import expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context';
import {
TRANSFORM_STATE,
TransformPivotConfig,
TransformStats,
} from '../../../../legacy/plugins/transform/public/app/common';
export function TransformAPIProvider({ getService }: FtrProviderContext) {
const es = getService('legacyEs');
const log = getService('log');
const retry = getService('retry');
const esSupertest = getService('esSupertest');
return {
async deleteIndices(indices: string) {
@ -39,5 +46,89 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) {
async cleanTransformIndices() {
await this.deleteIndices('.transform-*');
},
async getTransformStats(transformId: string): Promise<TransformStats> {
log.debug(`Fetching transform stats for transform ${transformId}`);
const statsResponse = await esSupertest
.get(`/_transform/${transformId}/_stats`)
.expect(200)
.then((res: any) => res.body);
expect(statsResponse.transforms).to.have.length(1);
return statsResponse.transforms[0];
},
async getTransformState(transformId: string): Promise<TRANSFORM_STATE> {
const stats = await this.getTransformStats(transformId);
const state: TRANSFORM_STATE = stats.state;
return state;
},
async waitForTransformState(transformId: string, expectedState: TRANSFORM_STATE) {
await retry.waitForWithTimeout(
`transform state to be ${expectedState}`,
2 * 60 * 1000,
async () => {
const state = await this.getTransformState(transformId);
if (state === expectedState) {
return true;
} else {
throw new Error(`expected transform state to be ${expectedState} but got ${state}`);
}
}
);
},
async waitForBatchTransformToComplete(transformId: string) {
await retry.waitForWithTimeout(`batch transform to complete`, 2 * 60 * 1000, async () => {
const stats = await this.getTransformStats(transformId);
if (stats.state === TRANSFORM_STATE.STOPPED && stats.checkpointing.last.checkpoint === 1) {
return true;
} else {
throw new Error(
`expected batch transform to be stopped with last checkpoint = 1 (got status: '${stats.state}', checkpoint: '${stats.checkpointing.last.checkpoint}')`
);
}
});
},
async getTransform(transformId: string) {
return await esSupertest.get(`/_transform/${transformId}`).expect(200);
},
async createTransform(transformConfig: TransformPivotConfig) {
const transformId = transformConfig.id;
log.debug(`Creating transform with id '${transformId}'...`);
await esSupertest
.put(`/_transform/${transformId}`)
.send(transformConfig)
.expect(200);
await retry.waitForWithTimeout(`'${transformId}' to be created`, 5 * 1000, async () => {
if (await this.getTransform(transformId)) {
return true;
} else {
throw new Error(`expected transform '${transformId}' to be created`);
}
});
},
async startTransform(transformId: string) {
log.debug(`Starting transform '${transformId}' ...`);
await esSupertest.post(`/_transform/${transformId}/_start`).expect(200);
},
async createAndRunTransform(transformConfig: TransformPivotConfig) {
await this.createTransform(transformConfig);
await this.startTransform(transformConfig.id);
if (transformConfig.sync === undefined) {
// batch mode
await this.waitForBatchTransformToComplete(transformConfig.id);
} else {
// continuous mode
await this.waitForTransformState(transformConfig.id, TRANSFORM_STATE.STARTED);
}
},
};
}