Added server api tests for event log service (#63540)

* Added server api tests for event log service

* fixed tests

* fixed type check issue

* Fixed failing tests

* fixed jest tests

* Fixed due to comments

* Removed flackiness tests

* fixed type check error

* Fixed func test
This commit is contained in:
Yuliia Naumenko 2020-04-17 09:50:08 -07:00 committed by GitHub
parent 675c5898ca
commit 2af91b3c51
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 520 additions and 54 deletions

View file

@ -19,6 +19,7 @@ const createContextMock = () => {
initialize: jest.fn(),
waitTillReady: jest.fn(),
esAdapter: clusterClientAdapterMock.create(),
initialized: true,
};
return mock;
};

View file

@ -0,0 +1,95 @@
/*
* 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 { createEsContext } from './context';
import { ClusterClient, Logger } from '../../../../../src/core/server';
import { elasticsearchServiceMock, loggingServiceMock } from '../../../../../src/core/server/mocks';
jest.mock('../lib/../../../../package.json', () => ({
version: '1.2.3',
}));
type EsClusterClient = Pick<jest.Mocked<ClusterClient>, 'callAsInternalUser' | 'asScoped'>;
let logger: Logger;
let clusterClient: EsClusterClient;
beforeEach(() => {
logger = loggingServiceMock.createLogger();
clusterClient = elasticsearchServiceMock.createClusterClient();
});
describe('createEsContext', () => {
test('should return is ready state as falsy if not initialized', () => {
const context = createEsContext({
logger,
clusterClientPromise: Promise.resolve(clusterClient),
indexNameRoot: 'test0',
});
expect(context.initialized).toBeFalsy();
context.initialize();
expect(context.initialized).toBeTruthy();
});
test('should return esNames', () => {
const context = createEsContext({
logger,
clusterClientPromise: Promise.resolve(clusterClient),
indexNameRoot: 'test-index',
});
const esNames = context.esNames;
expect(esNames).toStrictEqual({
base: 'test-index',
alias: 'test-index-event-log-1.2.3',
ilmPolicy: 'test-index-event-log-policy',
indexPattern: 'test-index-event-log-*',
indexPatternWithVersion: 'test-index-event-log-1.2.3-*',
indexTemplate: 'test-index-event-log-1.2.3-template',
initialIndex: 'test-index-event-log-1.2.3-000001',
});
});
test('should return exist false for esAdapter ilm policy, index template and alias before initialize', async () => {
const context = createEsContext({
logger,
clusterClientPromise: Promise.resolve(clusterClient),
indexNameRoot: 'test1',
});
clusterClient.callAsInternalUser.mockResolvedValue(false);
const doesAliasExist = await context.esAdapter.doesAliasExist(context.esNames.alias);
expect(doesAliasExist).toBeFalsy();
const doesIndexTemplateExist = await context.esAdapter.doesIndexTemplateExist(
context.esNames.indexTemplate
);
expect(doesIndexTemplateExist).toBeFalsy();
});
test('should return exist true for esAdapter ilm policy, index template and alias after initialize', async () => {
const context = createEsContext({
logger,
clusterClientPromise: Promise.resolve(clusterClient),
indexNameRoot: 'test2',
});
clusterClient.callAsInternalUser.mockResolvedValue(true);
context.initialize();
const doesIlmPolicyExist = await context.esAdapter.doesIlmPolicyExist(
context.esNames.ilmPolicy
);
expect(doesIlmPolicyExist).toBeTruthy();
const doesAliasExist = await context.esAdapter.doesAliasExist(context.esNames.alias);
expect(doesAliasExist).toBeTruthy();
const doesIndexTemplateExist = await context.esAdapter.doesIndexTemplateExist(
context.esNames.indexTemplate
);
expect(doesIndexTemplateExist).toBeTruthy();
});
});

View file

@ -19,6 +19,7 @@ export interface EsContext {
esAdapter: IClusterClientAdapter;
initialize(): void;
waitTillReady(): Promise<boolean>;
initialized: boolean;
}
export interface EsError {
@ -41,7 +42,7 @@ class EsContextImpl implements EsContext {
public readonly esNames: EsNames;
public esAdapter: IClusterClientAdapter;
private readonly readySignal: ReadySignal<boolean>;
private initialized: boolean;
public initialized: boolean;
constructor(params: EsContextCtorParams) {
this.logger = params.logger;

View file

@ -0,0 +1,228 @@
/*
* 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 {
RequestHandlerContext,
KibanaRequest,
KibanaResponseFactory,
IKibanaResponse,
IRouter,
Logger,
RouteValidationResultFactory,
} from 'kibana/server';
import { IEventLogService, IEventLogger } from '../../../../../plugins/event_log/server';
import { IValidatedEvent } from '../../../../../plugins/event_log/server/types';
export const logEventRoute = (router: IRouter, eventLogger: IEventLogger, logger: Logger) => {
router.post(
{
path: `/api/log_event_fixture/{id}/_log`,
validate: {
// removed validation as schema is currently broken in tests
// blocked by: https://github.com/elastic/kibana/issues/61652
params: (value: any, { ok }: RouteValidationResultFactory) => ok(value),
body: (value: any, { ok }: RouteValidationResultFactory) => ok(value),
},
},
async function(
context: RequestHandlerContext,
req: KibanaRequest<any, any, any, any>,
res: KibanaResponseFactory
): Promise<IKibanaResponse<any>> {
const { id } = req.params as { id: string };
const event: IValidatedEvent = req.body;
logger.info(`test fixture: log event: ${id} ${JSON.stringify(event)}`);
try {
await context.core.savedObjects.client.get('event_log_test', id);
logger.info(`found existing saved object`);
} catch (ex) {
logger.info(`log event error: ${ex}`);
await context.core.savedObjects.client.create('event_log_test', {}, { id });
logger.info(`created saved object`);
}
eventLogger.logEvent(event);
logger.info(`logged`);
return res.ok({});
}
);
};
export const registerProviderActionsRoute = (
router: IRouter,
eventLogService: IEventLogService,
logger: Logger
) => {
router.post(
{
path: '/api/log_event_fixture/{provider}/_registerProviderActions',
validate: {
body: value => ({ value }),
params: (value: any, { ok }: RouteValidationResultFactory) => ok(value),
},
options: { authRequired: false },
},
(context, request, response) => {
const { provider } = request.params as { provider: string };
const actions = request.body;
try {
logger.info(
`test register provider actions: ${provider}, actions: ${JSON.stringify(actions)}`
);
eventLogService.registerProviderActions(provider, actions);
logger.info(`registered`);
} catch (e) {
return response.badRequest({ body: e });
}
return response.ok({ body: {} });
}
);
};
export const isProviderActionRegisteredRoute = (
router: IRouter,
eventLogService: IEventLogService,
logger: Logger
) => {
router.get(
{
path: `/api/log_event_fixture/{provider}/{action}/_isProviderActionRegistered`,
validate: {
params: (value: any, { ok }: RouteValidationResultFactory) => ok(value),
},
},
async function(
context: RequestHandlerContext,
req: KibanaRequest<any, any, any, any>,
res: KibanaResponseFactory
): Promise<IKibanaResponse<any>> {
const { provider, action } = req.params as { provider: string; action: string };
logger.info(`test provider actions is registered: ${provider} for action: ${action}`);
return res.ok({
body: {
isProviderActionRegistered: eventLogService.isProviderActionRegistered(provider, action),
},
});
}
);
};
export const getProviderActionsRoute = (
router: IRouter,
eventLogService: IEventLogService,
logger: Logger
) => {
router.get(
{
path: `/api/log_event_fixture/{provider}/getProviderActions`,
validate: {
params: (value: any, { ok }: RouteValidationResultFactory) => ok(value),
},
},
async function(
context: RequestHandlerContext,
req: KibanaRequest<any, any, any, any>,
res: KibanaResponseFactory
): Promise<IKibanaResponse<any>> {
const { provider } = req.params as { provider: string };
logger.info(`test if get all provider actions is registered`);
return res.ok({
body: { actions: [...(eventLogService.getProviderActions().get(provider) ?? [])] },
});
}
);
};
export const getLoggerRoute = (
router: IRouter,
eventLogService: IEventLogService,
logger: Logger
) => {
router.get(
{
path: `/api/log_event_fixture/getEventLogger/{event}`,
validate: {
params: (value: any, { ok }: RouteValidationResultFactory) => ok(value),
},
},
async function(
context: RequestHandlerContext,
req: KibanaRequest<any, any, any, any>,
res: KibanaResponseFactory
): Promise<IKibanaResponse<any>> {
const { event } = req.params as { event: string };
logger.info(`test get event logger for event: ${event}`);
return res.ok({
body: { eventLogger: eventLogService.getLogger({ event: { provider: event } }) },
});
}
);
};
export const isIndexingEntriesRoute = (
router: IRouter,
eventLogService: IEventLogService,
logger: Logger
) => {
router.get(
{
path: `/api/log_event_fixture/isIndexingEntries`,
validate: {},
},
async function(
context: RequestHandlerContext,
req: KibanaRequest<any, any, any, any>,
res: KibanaResponseFactory
): Promise<IKibanaResponse<any>> {
logger.info(`test if event logger is indexing entries`);
return res.ok({ body: { isIndexingEntries: eventLogService.isIndexingEntries() } });
}
);
};
export const isEventLogServiceEnabledRoute = (
router: IRouter,
eventLogService: IEventLogService,
logger: Logger
) => {
router.get(
{
path: `/api/log_event_fixture/isEventLogServiceEnabled`,
validate: {},
},
async function(
context: RequestHandlerContext,
req: KibanaRequest<any, any, any, any>,
res: KibanaResponseFactory
): Promise<IKibanaResponse<any>> {
logger.info(`test if event logger is enabled`);
return res.ok({ body: { isEnabled: eventLogService.isEnabled() } });
}
);
};
export const isEventLogServiceLoggingEntriesRoute = (
router: IRouter,
eventLogService: IEventLogService,
logger: Logger
) => {
router.get(
{
path: `/api/log_event_fixture/isEventLogServiceLoggingEntries`,
validate: {},
},
async function(
context: RequestHandlerContext,
req: KibanaRequest<any, any, any, any>,
res: KibanaResponseFactory
): Promise<IKibanaResponse<any>> {
logger.info(`test if event logger is logging entries`);
return res.ok({ body: { isLoggingEntries: eventLogService.isLoggingEntries() } });
}
);
};

View file

@ -4,24 +4,18 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { Plugin, CoreSetup, Logger, PluginInitializerContext } from 'kibana/server';
import { IEventLogService, IEventLogClientService } from '../../../../../plugins/event_log/server';
import {
Plugin,
CoreSetup,
RequestHandlerContext,
KibanaRequest,
KibanaResponseFactory,
IKibanaResponse,
IRouter,
Logger,
PluginInitializerContext,
RouteValidationResultFactory,
} from 'kibana/server';
import {
IEventLogService,
IEventLogClientService,
IEventLogger,
} from '../../../../../plugins/event_log/server';
import { IValidatedEvent } from '../../../../../plugins/event_log/server/types';
logEventRoute,
registerProviderActionsRoute,
isProviderActionRegisteredRoute,
getProviderActionsRoute,
getLoggerRoute,
isIndexingEntriesRoute,
isEventLogServiceLoggingEntriesRoute,
isEventLogServiceEnabledRoute,
} from './init_routes';
// this plugin's dependendencies
export interface EventLogFixtureSetupDeps {
@ -57,42 +51,17 @@ export class EventLogFixturePlugin
});
logEventRoute(router, eventLogger, this.logger);
// event log service api routes
registerProviderActionsRoute(router, eventLog, this.logger);
isProviderActionRegisteredRoute(router, eventLog, this.logger);
getProviderActionsRoute(router, eventLog, this.logger);
getLoggerRoute(router, eventLog, this.logger);
isIndexingEntriesRoute(router, eventLog, this.logger);
isEventLogServiceLoggingEntriesRoute(router, eventLog, this.logger);
isEventLogServiceEnabledRoute(router, eventLog, this.logger);
}
public start() {}
public stop() {}
}
const logEventRoute = (router: IRouter, eventLogger: IEventLogger, logger: Logger) => {
router.post(
{
path: `/api/log_event_fixture/{id}/_log`,
validate: {
// removed validation as schema is currently broken in tests
// blocked by: https://github.com/elastic/kibana/issues/61652
params: (value: any, { ok }: RouteValidationResultFactory) => ok(value),
body: (value: any, { ok }: RouteValidationResultFactory) => ok(value),
},
},
async function(
context: RequestHandlerContext,
req: KibanaRequest<any, any, any, any>,
res: KibanaResponseFactory
): Promise<IKibanaResponse<any>> {
const { id } = req.params as { id: string };
const event: IValidatedEvent = req.body;
logger.info(`test fixture: log event: ${id} ${JSON.stringify(event)}`);
try {
await context.core.savedObjects.client.get('event_log_test', id);
logger.info(`found existing saved object`);
} catch (ex) {
logger.info(`log event error: ${ex}`);
await context.core.savedObjects.client.create('event_log_test', {}, { id });
logger.info(`created saved object`);
}
eventLogger.logEvent(event);
logger.info(`logged`);
return res.ok({});
}
);
};

View file

@ -3,9 +3,181 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import expect from '@kbn/expect/expect.js';
import { IEvent } from '../../../../plugins/event_log/server';
import { FtrProviderContext } from '../../ftr_provider_context';
export default function({ getService }: FtrProviderContext) {
const es = getService('legacyEs');
const supertest = getService('supertest');
const log = getService('log');
const config = getService('config');
const retry = getService('retry');
export default function() {
describe('Event Log service API', () => {
it('should allow logging an event', async () => {});
it('should check if it is enabled', async () => {
const configValue = config
.get('kbnTestServer.serverArgs')
.find((val: string) => val === '--xpack.eventLog.enabled=true');
const result = await isEventLogServiceEnabled();
expect(configValue).to.be.eql(`--xpack.eventLog.enabled=${result.body.isEnabled}`);
});
it('should check if logging entries is enabled', async () => {
const configValue = config
.get('kbnTestServer.serverArgs')
.find((val: string) => val === '--xpack.eventLog.logEntries=true');
const result = await isEventLogServiceLoggingEntries();
expect(configValue).to.be.eql(`--xpack.eventLog.logEntries=${result.body.isLoggingEntries}`);
});
it('should check if indexing entries is enabled', async () => {
const configValue = config
.get('kbnTestServer.serverArgs')
.find((val: string) => val === '--xpack.eventLog.indexEntries=true');
const result = await isIndexingEntries();
const exists = await es.indices.exists({ index: '.kibana-event-log-*' });
expect(exists).to.be.eql(true);
expect(configValue).to.be.eql(
`--xpack.eventLog.indexEntries=${result.body.isIndexingEntries}`
);
});
it('should be able to check if provider actions is registered', async () => {
const initResult = await isProviderActionRegistered('provider3', 'action1');
if (!initResult.body.isProviderActionRegistered) {
await registerProviderActions('provider3', ['action1']);
}
const result1 = await isProviderActionRegistered('provider3', 'action1');
expect(result1.body.isProviderActionRegistered).to.be.eql(true);
const result = await isProviderActionRegistered('provider3', 'action2');
expect(result.body.isProviderActionRegistered).to.be.eql(false);
});
it('should return error message if provider is registered', async () => {
const initResult = await isProviderActionRegistered('duplication', 'action1');
if (!initResult.body.isProviderActionRegistered) {
await registerProviderActions('duplication', ['action1', 'action2']);
}
const result = await registerProviderActions('duplication', ['action1', 'action2']);
expect(result.badRequest).to.be.eql(true);
});
it('should allow to register provider actions and return all provider actions', async () => {
const initResult = await isProviderActionRegistered('provider1', 'action1');
if (!initResult.body.isProviderActionRegistered) {
await registerProviderActions('provider1', ['action1', 'action2']);
}
const providerActions = await getProviderActions('provider1');
expect(providerActions.body.actions).to.be.eql(['action1', 'action2']);
});
it('should allow to get event logger event log service', async () => {
const initResult = await isProviderActionRegistered('provider2', 'action1');
if (!initResult.body.isProviderActionRegistered) {
await registerProviderActions('provider2', ['action1', 'action2']);
}
const eventLogger = await getEventLogger('provider2');
expect(eventLogger.body.eventLogger.initialProperties).to.be.eql({
event: { provider: 'provider2' },
});
});
it('should allow write an event to index document if indexing entries is enabled', async () => {
const initResult = await isProviderActionRegistered('provider4', 'action1');
if (!initResult.body.isProviderActionRegistered) {
await registerProviderActions('provider4', ['action1', 'action2']);
}
const eventId = '1';
const event: IEvent = {
event: { action: 'action1', provider: 'provider4' },
kibana: { saved_objects: [{ type: 'event_log_test', id: eventId }] },
};
await logTestEvent(eventId, event);
await retry.try(async () => {
const uri = `/api/event_log/event_log_test/${eventId}/_find`;
log.debug(`calling ${uri}`);
const result = await supertest
.get(uri)
.set('kbn-xsrf', 'foo')
.expect(200);
expect(result.body.data.length).to.be.eql(1);
});
});
});
async function registerProviderActions(provider: string, actions: string[]) {
log.debug(`registerProviderActions ${provider}`);
return await supertest
.post(`/api/log_event_fixture/${provider}/_registerProviderActions`)
.set('kbn-xsrf', 'xxx')
.send(actions);
}
async function isProviderActionRegistered(provider: string, action: string) {
log.debug(`isProviderActionRegistered ${provider} for action ${action}`);
return await supertest
.get(`/api/log_event_fixture/${provider}/${action}/_isProviderActionRegistered`)
.set('kbn-xsrf', 'foo')
.expect(200);
}
async function getProviderActions(provider: string) {
log.debug(`getProviderActions ${provider}`);
return await supertest
.get(`/api/log_event_fixture/${provider}/getProviderActions`)
.set('kbn-xsrf', 'xxx')
.expect(200);
}
async function getEventLogger(event: string) {
log.debug(`isProviderActionRegistered for event ${event}`);
return await supertest
.get(`/api/log_event_fixture/getEventLogger/${event}`)
.set('kbn-xsrf', 'foo')
.expect(200);
}
async function isIndexingEntries() {
log.debug(`isIndexingEntries`);
return await supertest
.get(`/api/log_event_fixture/isIndexingEntries`)
.set('kbn-xsrf', 'foo')
.expect(200);
}
async function isEventLogServiceEnabled() {
log.debug(`isEventLogServiceEnabled`);
return await supertest
.get(`/api/log_event_fixture/isEventLogServiceEnabled`)
.set('kbn-xsrf', 'foo')
.expect(200);
}
async function isEventLogServiceLoggingEntries() {
log.debug(`isEventLogServiceLoggingEntries`);
return await supertest
.get(`/api/log_event_fixture/isEventLogServiceLoggingEntries`)
.set('kbn-xsrf', 'foo')
.expect(200);
}
async function logTestEvent(id: string, event: IEvent) {
log.debug(`Logging Event for Saved Object ${id}`);
return await supertest
.post(`/api/log_event_fixture/${id}/_log`)
.set('kbn-xsrf', 'foo')
.send(event)
.expect(200);
}
}