kibana/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.test.ts

365 lines
11 KiB
TypeScript

/*
* 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 { kibanaResponseFactory, RequestHandler } from 'src/core/server';
import { createMockRouter, MockRouter, routeHandlerContextMock } from './__mocks__/routes.mock';
import { createRequestMock } from './__mocks__/request.mock';
import { registerMlSnapshotRoutes } from './ml_snapshots';
jest.mock('../lib/es_version_precheck', () => ({
versionCheckHandlerWrapper: <P, Q, B>(handler: RequestHandler<P, Q, B>) => handler,
}));
const JOB_ID = 'job_id';
const SNAPSHOT_ID = 'snapshot_id';
const NODE_ID = 'node_id';
describe('ML snapshots APIs', () => {
let mockRouter: MockRouter;
let routeDependencies: any;
beforeEach(() => {
mockRouter = createMockRouter();
routeDependencies = {
router: mockRouter,
};
registerMlSnapshotRoutes(routeDependencies);
});
afterEach(() => {
jest.resetAllMocks();
});
describe('POST /api/upgrade_assistant/ml_snapshots', () => {
it('returns 200 status and in_progress status', async () => {
(routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.ml
.upgradeJobSnapshot as jest.Mock).mockResolvedValue({
body: {
node: NODE_ID,
completed: false,
},
});
const resp = await routeDependencies.router.getHandler({
method: 'post',
pathPattern: '/api/upgrade_assistant/ml_snapshots',
})(
routeHandlerContextMock,
createRequestMock({
body: {
snapshotId: SNAPSHOT_ID,
jobId: JOB_ID,
},
}),
kibanaResponseFactory
);
expect(resp.status).toEqual(200);
expect(resp.payload).toEqual({
jobId: JOB_ID,
nodeId: NODE_ID,
snapshotId: SNAPSHOT_ID,
status: 'in_progress',
});
});
it('returns 200 status and complete status', async () => {
(routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.ml
.upgradeJobSnapshot as jest.Mock).mockResolvedValue({
body: {
node: NODE_ID,
completed: true,
},
});
const resp = await routeDependencies.router.getHandler({
method: 'post',
pathPattern: '/api/upgrade_assistant/ml_snapshots',
})(
routeHandlerContextMock,
createRequestMock({
body: {
snapshotId: SNAPSHOT_ID,
jobId: JOB_ID,
},
}),
kibanaResponseFactory
);
expect(resp.status).toEqual(200);
expect(resp.payload).toEqual({
jobId: JOB_ID,
nodeId: NODE_ID,
snapshotId: SNAPSHOT_ID,
status: 'complete',
});
});
it('returns an error if it throws', async () => {
(routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.ml
.upgradeJobSnapshot as jest.Mock).mockRejectedValue(new Error('scary error!'));
await expect(
routeDependencies.router.getHandler({
method: 'post',
pathPattern: '/api/upgrade_assistant/ml_snapshots',
})(
routeHandlerContextMock,
createRequestMock({
body: {
snapshotId: SNAPSHOT_ID,
jobId: JOB_ID,
},
}),
kibanaResponseFactory
)
).rejects.toThrow('scary error!');
});
});
describe('DELETE /api/upgrade_assistant/ml_snapshots/:jobId/:snapshotId', () => {
it('returns 200 status', async () => {
(routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.ml
.deleteModelSnapshot as jest.Mock).mockResolvedValue({
body: { acknowledged: true },
});
const resp = await routeDependencies.router.getHandler({
method: 'delete',
pathPattern: '/api/upgrade_assistant/ml_snapshots/{jobId}/{snapshotId}',
})(
routeHandlerContextMock,
createRequestMock({
params: { snapshotId: 'snapshot_id1', jobId: 'job_id1' },
}),
kibanaResponseFactory
);
expect(resp.status).toEqual(200);
expect(resp.payload).toEqual({
acknowledged: true,
});
});
it('returns an error if it throws', async () => {
(routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.ml
.deleteModelSnapshot as jest.Mock).mockRejectedValue(new Error('scary error!'));
await expect(
routeDependencies.router.getHandler({
method: 'delete',
pathPattern: '/api/upgrade_assistant/ml_snapshots/{jobId}/{snapshotId}',
})(
routeHandlerContextMock,
createRequestMock({
params: { snapshotId: 'snapshot_id1', jobId: 'job_id1' },
}),
kibanaResponseFactory
)
).rejects.toThrow('scary error!');
});
});
describe('GET /api/upgrade_assistant/ml_snapshots/:jobId/:snapshotId', () => {
it('returns "idle" status if saved object does not exist', async () => {
(routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.ml
.getModelSnapshots as jest.Mock).mockResolvedValue({
body: {
count: 1,
model_snapshots: [
{
job_id: JOB_ID,
min_version: '6.4.0',
timestamp: 1575402237000,
description: 'State persisted due to job close at 2019-12-03T19:43:57+0000',
snapshot_id: SNAPSHOT_ID,
snapshot_doc_count: 1,
model_size_stats: {},
latest_record_time_stamp: 1576971072000,
latest_result_time_stamp: 1576965600000,
retain: false,
},
],
},
});
const resp = await routeDependencies.router.getHandler({
method: 'get',
pathPattern: '/api/upgrade_assistant/ml_snapshots/{jobId}/{snapshotId}',
})(
routeHandlerContextMock,
createRequestMock({
params: {
snapshotId: SNAPSHOT_ID,
jobId: JOB_ID,
},
}),
kibanaResponseFactory
);
expect(resp.status).toEqual(200);
expect(resp.payload).toEqual({
jobId: JOB_ID,
nodeId: undefined,
snapshotId: SNAPSHOT_ID,
status: 'idle',
});
});
it('returns "in_progress" status if snapshot upgrade is in progress', async () => {
(routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.ml
.getModelSnapshots as jest.Mock).mockResolvedValue({
body: {
count: 1,
model_snapshots: [
{
job_id: JOB_ID,
min_version: '6.4.0',
timestamp: 1575402237000,
description: 'State persisted due to job close at 2019-12-03T19:43:57+0000',
snapshot_id: SNAPSHOT_ID,
snapshot_doc_count: 1,
model_size_stats: {},
latest_record_time_stamp: 1576971072000,
latest_result_time_stamp: 1576965600000,
retain: false,
},
],
},
});
(routeHandlerContextMock.core.savedObjects.client.find as jest.Mock).mockResolvedValue({
total: 1,
saved_objects: [
{
attributes: {
nodeId: NODE_ID,
jobId: JOB_ID,
snapshotId: SNAPSHOT_ID,
},
},
],
});
(routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.tasks
.list as jest.Mock).mockResolvedValue({
body: {
nodes: {
[NODE_ID]: {
tasks: {
[`${NODE_ID}:12345`]: {
description: `job-snapshot-upgrade-${JOB_ID}-${SNAPSHOT_ID}`,
},
},
},
},
},
});
const resp = await routeDependencies.router.getHandler({
method: 'get',
pathPattern: '/api/upgrade_assistant/ml_snapshots/{jobId}/{snapshotId}',
})(
routeHandlerContextMock,
createRequestMock({
params: {
snapshotId: SNAPSHOT_ID,
jobId: JOB_ID,
},
}),
kibanaResponseFactory
);
expect(resp.status).toEqual(200);
expect(resp.payload).toEqual({
jobId: JOB_ID,
nodeId: NODE_ID,
snapshotId: SNAPSHOT_ID,
status: 'in_progress',
});
});
it('returns "complete" status if snapshot upgrade has completed', async () => {
(routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.ml
.getModelSnapshots as jest.Mock).mockResolvedValue({
body: {
count: 1,
model_snapshots: [
{
job_id: JOB_ID,
min_version: '6.4.0',
timestamp: 1575402237000,
description: 'State persisted due to job close at 2019-12-03T19:43:57+0000',
snapshot_id: SNAPSHOT_ID,
snapshot_doc_count: 1,
model_size_stats: {},
latest_record_time_stamp: 1576971072000,
latest_result_time_stamp: 1576965600000,
retain: false,
},
],
},
});
(routeHandlerContextMock.core.savedObjects.client.find as jest.Mock).mockResolvedValue({
total: 1,
saved_objects: [
{
attributes: {
nodeId: NODE_ID,
jobId: JOB_ID,
snapshotId: SNAPSHOT_ID,
},
},
],
});
(routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.tasks
.list as jest.Mock).mockResolvedValue({
body: {
nodes: {
[NODE_ID]: {
tasks: {},
},
},
},
});
(routeHandlerContextMock.core.elasticsearch.client.asCurrentUser.migration
.deprecations as jest.Mock).mockResolvedValue({
body: {
cluster_settings: [],
ml_settings: [],
node_settings: [],
index_settings: {},
},
});
(routeHandlerContextMock.core.savedObjects.client.delete as jest.Mock).mockResolvedValue({});
const resp = await routeDependencies.router.getHandler({
method: 'get',
pathPattern: '/api/upgrade_assistant/ml_snapshots/{jobId}/{snapshotId}',
})(
routeHandlerContextMock,
createRequestMock({
params: {
snapshotId: SNAPSHOT_ID,
jobId: JOB_ID,
},
}),
kibanaResponseFactory
);
expect(resp.status).toEqual(200);
expect(resp.payload).toEqual({
jobId: JOB_ID,
nodeId: NODE_ID,
snapshotId: SNAPSHOT_ID,
status: 'complete',
});
});
});
});