Skip to content

Commit

Permalink
[Endpoint] Fix endpoint tests with data streams (#68794)
Browse files Browse the repository at this point in the history
* Temporary fix to get tests working again with data streams

* Removing mappings and renabling tests

* optionally using create for our tests only has a stop gap

* Adding default for internal function

* Removing tests that could fail if backing index changes

* Removing unused import

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
jonathan-buttner and elasticmachine committed Jun 11, 2020
1 parent 0d0ea70 commit 8288386
Show file tree
Hide file tree
Showing 13 changed files with 79 additions and 3,246 deletions.
4 changes: 3 additions & 1 deletion src/es_archiver/actions/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@ const pipeline = (...streams: Readable[]) =>
export async function loadAction({
name,
skipExisting,
useCreate,
client,
dataDir,
log,
kbnClient,
}: {
name: string;
skipExisting: boolean;
useCreate: boolean;
client: Client;
dataDir: string;
log: ToolingLog;
Expand Down Expand Up @@ -87,7 +89,7 @@ export async function loadAction({
await createPromiseFromStreams([
recordStream,
createCreateIndexStream({ client, stats, skipExisting, log }),
createIndexDocRecordsStream(client, stats, progress),
createIndexDocRecordsStream(client, stats, progress, useCreate),
]);

progress.deactivate();
Expand Down
10 changes: 9 additions & 1 deletion src/es_archiver/es_archiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,20 @@ export class EsArchiver {
* @param {Object} options
* @property {Boolean} options.skipExisting - should existing indices
* be ignored or overwritten
* @property {Boolean} options.useCreate - use a create operation instead of index for documents
* @return Promise<Stats>
*/
async load(name: string, { skipExisting = false }: { skipExisting?: boolean } = {}) {
async load(
name: string,
{
skipExisting = false,
useCreate = false,
}: { skipExisting?: boolean; useCreate?: boolean } = {}
) {
return await loadAction({
name,
skipExisting: !!skipExisting,
useCreate: !!useCreate,
client: this.client,
dataDir: this.dataDir,
log: this.log,
Expand Down
11 changes: 8 additions & 3 deletions src/es_archiver/lib/docs/index_doc_records_stream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,20 @@ import { Writable } from 'stream';
import { Stats } from '../stats';
import { Progress } from '../progress';

export function createIndexDocRecordsStream(client: Client, stats: Stats, progress: Progress) {
export function createIndexDocRecordsStream(
client: Client,
stats: Stats,
progress: Progress,
useCreate: boolean = false
) {
async function indexDocs(docs: any[]) {
const body: any[] = [];

const operation = useCreate === true ? 'create' : 'index';
docs.forEach((doc) => {
stats.indexedDoc(doc.index);
body.push(
{
index: {
[operation]: {
_index: doc.index,
_type: doc.type,
_id: doc.id,
Expand Down
51 changes: 8 additions & 43 deletions x-pack/test/api_integration/apis/endpoint/alerts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import expect from '@kbn/expect/expect.js';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { AlertData } from '../../../../../plugins/security_solution/common/endpoint_alerts/types';
import { AlertId } from '../../../../../plugins/security_solution/server/endpoint/alerts/handlers/lib/index';
import { deleteEventsStream, deleteMetadataStream } from '../data_stream_helper';

/**
* The number of alert documents in the es archive.
Expand Down Expand Up @@ -66,26 +66,25 @@ export default function ({ getService }: FtrProviderContext) {
const nextPrevPrefixOrder = 'order=desc';
const nextPrevPrefixPageSize = 'page_size=10';
const nextPrevPrefix = `${nextPrevPrefixQuery}&${nextPrevPrefixDateRange}&${nextPrevPrefixSort}&${nextPrevPrefixOrder}&${nextPrevPrefixPageSize}`;
const alertIndex = 'events-endpoint-1';

let nullableEventId = '';

// SKIPPED as it is failing ES PROMOTION: https://github.com/elastic/kibana/issues/68613
describe.skip('Endpoint alert API', () => {
describe('Endpoint alert API', () => {
describe('when data is in elasticsearch', () => {
before(async () => {
await esArchiver.load('endpoint/alerts/api_feature');
await esArchiver.load('endpoint/alerts/host_api_feature');
await esArchiver.load('endpoint/alerts/api_feature', { useCreate: true });
await esArchiver.load('endpoint/alerts/host_api_feature', { useCreate: true });
const res = await es.search({
index: alertIndex,
index: 'events-endpoint-*',
body: ES_QUERY_MISSING,
});
nullableEventId = res.hits.hits[0]._source.event.id;
});

after(async () => {
await esArchiver.unload('endpoint/alerts/api_feature');
await esArchiver.unload('endpoint/alerts/host_api_feature');
// the endpoint uses data streams and es archiver does not support deleting them at the moment so we need
// to do it manually
await Promise.all([deleteEventsStream(getService), deleteMetadataStream(getService)]);
});

it('should not support POST requests', async () => {
Expand Down Expand Up @@ -375,40 +374,6 @@ export default function ({ getService }: FtrProviderContext) {
expect(body.result_from_index).to.eql(0);
});

it('should return alert details by id, getting last alert', async () => {
const documentID = new AlertId(alertIndex, 'zbNm0HABdD75WLjLYgcB');
const prevDocumentID = new AlertId(alertIndex, '2rNm0HABdD75WLjLYgcU');
const { body } = await supertest
.get(`/api/endpoint/alerts/${documentID.toString()}`)
.set('kbn-xsrf', 'xxx')
.expect(200);
expect(body.id).to.eql(documentID.toString());
expect(body.prev).to.eql(`/api/endpoint/alerts/${prevDocumentID.toString()}`);
expect(body.next).to.eql(null); // last alert, no more beyond this
expect(body.state.host_metadata.host.id).to.eql(body.host.id);
});

it('should return alert details by id, getting first alert', async () => {
const documentID = new AlertId(alertIndex, 'p7Nm0HABdD75WLjLYghv');
const nextDocumentID = new AlertId(alertIndex, 'mbNm0HABdD75WLjLYgho');
const { body } = await supertest
.get(`/api/endpoint/alerts/${documentID.toString()}`)
.set('kbn-xsrf', 'xxx')
.expect(200);
expect(body.id).to.eql(documentID.toString());
expect(body.next).to.eql(`/api/endpoint/alerts/${nextDocumentID.toString()}`);
expect(body.prev).to.eql(null); // first alert, no more before this
});

it('should return 404 when alert is not found', async () => {
const documentID = new AlertId(alertIndex, 'does-not-exit');

await supertest
.get(`/api/endpoint/alerts/${documentID.toString()}`)
.set('kbn-xsrf', 'xxx')
.expect(404);
});

it('should return 400 when alert id is not valid', async () => {
await supertest
.get('/api/endpoint/alerts/does-not-exist')
Expand Down
32 changes: 32 additions & 0 deletions x-pack/test/api_integration/apis/endpoint/data_stream_helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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 { Client } from '@elastic/elasticsearch';

export async function deleteDataStream(getService: (serviceName: 'es') => Client, index: string) {
const client = getService('es');
await client.transport.request(
{
method: 'DELETE',
path: `_data_stream/${index}`,
},
{
ignore: [404],
}
);
}

export async function deleteMetadataStream(getService: (serviceName: 'es') => Client) {
await deleteDataStream(getService, 'metrics-endpoint.metadata-*');
}

export async function deleteEventsStream(getService: (serviceName: 'es') => Client) {
await deleteDataStream(getService, 'events-endpoint-*');
}

export async function deletePolicyStream(getService: (serviceName: 'es') => Client) {
await deleteDataStream(getService, 'metrics-endpoint.policy-*');
}
16 changes: 11 additions & 5 deletions x-pack/test/api_integration/apis/endpoint/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
import expect from '@kbn/expect/expect.js';
import { FtrProviderContext } from '../../ftr_provider_context';
import { deleteMetadataStream } from './data_stream_helper';

/**
* The number of host documents in the es archive.
Expand All @@ -14,11 +15,12 @@ const numberOfHostsInFixture = 3;
export default function ({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const supertest = getService('supertest');
// SKIPPED as it is failing on ES PROMOTION: https://github.com/elastic/kibana/issues/68584
describe.skip('test metadata api', () => {
describe('test metadata api', () => {
describe('POST /api/endpoint/metadata when index is empty', () => {
it('metadata api should return empty result when index is empty', async () => {
await esArchiver.unload('endpoint/metadata/api_feature');
// the endpoint uses data streams and es archiver does not support deleting them at the moment so we need
// to do it manually
await deleteMetadataStream(getService);
const { body } = await supertest
.post('/api/endpoint/metadata')
.set('kbn-xsrf', 'xxx')
Expand All @@ -32,8 +34,12 @@ export default function ({ getService }: FtrProviderContext) {
});

describe('POST /api/endpoint/metadata when index is not empty', () => {
before(() => esArchiver.load('endpoint/metadata/api_feature'));
after(() => esArchiver.unload('endpoint/metadata/api_feature'));
before(
async () => await esArchiver.load('endpoint/metadata/api_feature', { useCreate: true })
);
// the endpoint uses data streams and es archiver does not support deleting them at the moment so we need
// to do it manually
after(async () => await deleteMetadataStream(getService));
it('metadata api should return one entry for each host with default paging', async () => {
const { body } = await supertest
.post('/api/endpoint/metadata')
Expand Down
10 changes: 6 additions & 4 deletions x-pack/test/api_integration/apis/endpoint/policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,18 @@

import expect from '@kbn/expect/expect.js';
import { FtrProviderContext } from '../../ftr_provider_context';
import { deletePolicyStream } from './data_stream_helper';

export default function ({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const supertest = getService('supertest');
// SKIPPED as it is failing ES PROMOTION: https://github.com/elastic/kibana/issues/68638
describe.skip('Endpoint policy api', () => {
describe('Endpoint policy api', () => {
describe('GET /api/endpoint/policy_response', () => {
before(async () => await esArchiver.load('endpoint/policy'));
before(async () => await esArchiver.load('endpoint/policy', { useCreate: true }));

after(async () => await esArchiver.unload('endpoint/policy'));
// the endpoint uses data streams and es archiver does not support deleting them at the moment so we need
// to do it manually
after(async () => await deletePolicyStream(getService));

it('should return one policy response for host', async () => {
const expectedHostId = '4f3b9858-a96d-49d8-a326-230d7763d767';
Expand Down
1 change: 1 addition & 0 deletions x-pack/test/api_integration/apis/endpoint/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ export default function resolverAPIIntegrationTests({ getService }: FtrProviderC
});
after(async () => {
await resolver.deleteTrees(resolverTrees);
// this unload is for an endgame-* index so it does not use data streams
await esArchiver.unload('endpoint/resolver/api_feature');
});

Expand Down
Loading

0 comments on commit 8288386

Please sign in to comment.