Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added mocks and logging #24743

Merged
merged 2 commits into from
Oct 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions x-pack/plugins/secops/server/graphql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,54 @@
*/

import { rootSchema } from '../../common/graphql/root/schema.gql';
import sourceMock from '../graphql/sources/source.mock';
import sourcesMock from '../graphql/sources/sources.mock';
import { Logger } from '../utils/logger';
import { sourcesSchema } from './sources/schema.gql';

export const schemas = [rootSchema, sourcesSchema];

// The types from graphql-tools/src/mock.ts 'any' based. I add slightly
// stricter types here, but these should go away when graphql-tools using something
// other than "any" in the future for its types.
// https://github.com/apollographql/graphql-tools/blob/master/src/mock.ts#L406
interface Context {
req: {
payload: {
operationName: string;
};
};
}

export const createMocks = (logger: Logger) => ({
Query: () => ({
allSources: (root: unknown, args: unknown, context: Context) => {
logger.info('Mock allSources');
const operationName = context.req.payload.operationName.toLowerCase();
switch (operationName) {
case 'test': {
logger.info(`Using mock for test ${sourceMock}`);
return sourcesMock;
}
default: {
logger.error(`Could not find a mock for: ${operationName}`);
return [];
}
}
},
source: (root: unknown, args: unknown, context: Context) => {
logger.info('Mock source');
const operationName = context.req.payload.operationName.toLowerCase();
switch (operationName) {
case 'test': {
logger.info(`Using mock for test ${sourceMock}`);
return sourceMock;
}
default: {
logger.error(`Could not find a mock for: ${operationName}`);
return {};
}
}
},
}),
});
17 changes: 17 additions & 0 deletions x-pack/plugins/secops/server/graphql/sources/source.mock.ts
Original file line number Diff line number Diff line change
@@ -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;
* you may not use this file except in compliance with the Elastic License.
*/

/* tslint:disable */

export default
{
"id": "default",
"configuration": {
"fields": {
"host": "beat.hostname"
}
}
}
24 changes: 24 additions & 0 deletions x-pack/plugins/secops/server/graphql/sources/sources.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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.
*/

/* tslint:disable */

export default
[
{
"id": "default",
"configuration": {
"fields": {
"container": "docker.container.name",
"host": "beat.hostname",
"message": [
"message",
"@message"
]
}
}
}
]
17 changes: 15 additions & 2 deletions x-pack/plugins/secops/server/init_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,29 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { IResolvers, makeExecutableSchema } from 'graphql-tools';
import { addMockFunctionsToSchema, IResolvers, makeExecutableSchema } from 'graphql-tools';

import { schemas } from './graphql';
import { createMocks } from './graphql';
import { createSourcesResolvers } from './graphql/sources';
import { AppBackendLibs } from './lib/types';
import { Logger } from './utils/logger';

export interface Config {
mocking: boolean;
logger: Logger;
}

export const initServer = (libs: AppBackendLibs) => {
export const initServer = (libs: AppBackendLibs, config: Config) => {
const { logger, mocking } = config;
const schema = makeExecutableSchema({
resolvers: [createSourcesResolvers(libs) as IResolvers],
typeDefs: schemas,
});

if (mocking) {
const mocks = createMocks(logger);
addMockFunctionsToSchema({ mocks, schema });
}
libs.framework.registerGraphQLEndpoint('/api/secops/graphql', schema);
};
25 changes: 25 additions & 0 deletions x-pack/plugins/secops/server/kibana.index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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 { amMocking } from './kibana.index';

describe('kibana.index', () => {
describe('#amMocking', () => {
afterEach(() => delete process.env.INGEST_MOCKS);

test('should return true when process.ENV.mocking is set to a lower case string true', () => {
process.env.INGEST_MOCKS = 'true';
expect(amMocking()).toEqual(true);
});
test('should return false when process.ENV.mocking is not set', () => {
expect(amMocking()).toEqual(false);
});
test('should return false when process.ENV.mocking is not set to a lower case string (since I am picky)', () => {
process.env.INGEST_MOCKS = 'TRUE';
expect(amMocking()).toEqual(false);
});
});
});
22 changes: 20 additions & 2 deletions x-pack/plugins/secops/server/kibana.index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,34 @@

import { Server } from 'hapi';
import JoiNamespace from 'joi';

import { initServer } from './init_server';
import { compose } from './lib/compose/kibana';
import { createLogger } from './utils/logger';

const APP_ID = 'secops';

export interface KbnServer extends Server {
usage: any;
usage: unknown;
}

export const amMocking = (): boolean => process.env.INGEST_MOCKS === 'true';

export const initServerWithKibana = (kbnServer: KbnServer) => {
const logger = createLogger(kbnServer);
logger.info('Plugin initializing');

const mocking = amMocking();
if (mocking) {
logger.info(
`Mocks for ${APP_ID} is activated. No real ${APP_ID} data will be used, only mocks will be used.`
);
}

const libs = compose(kbnServer);
initServer(libs);
initServer(libs, { mocking, logger });

logger.info('Plugin done initializing');
};

export const getConfigSchema = (Joi: typeof JoiNamespace) => {
Expand Down
46 changes: 46 additions & 0 deletions x-pack/plugins/secops/server/utils/logger.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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 { createLogger } from './logger';

const APP_ID = 'secops';
const createMockServer = () => ({ log: jest.fn() });

describe('logger', () => {
describe('#createLogger', () => {
test('should log out debug', () => {
const kbnServer = createMockServer();
const logger = createLogger(kbnServer as any);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in the logger one, I should follow the no any advice even with tests where possible. I have a lot of:

const logger = createLogger(kbnServer as any);

I think I can change the logger interface to only use the hapi Logger interface instead of pushing the whole Kibana Server in. Let me try that and see what happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created issue for this per conversation to keep things moving forward quickly:
https://github.com/elastic/ingest-dev/issues/73

logger.debug('debug information');
expect(kbnServer.log.mock.calls[0][0]).toEqual(['debug', APP_ID]);
expect(kbnServer.log.mock.calls[0][1]).toEqual('debug information');
});

test('should log out info', () => {
const kbnServer = createMockServer();
const logger = createLogger(kbnServer as any);
logger.info('info information');
expect(kbnServer.log.mock.calls[0][0]).toEqual(['info', APP_ID]);
expect(kbnServer.log.mock.calls[0][1]).toEqual('info information');
});

test('should log out warn', () => {
const kbnServer = createMockServer();
const logger = createLogger(kbnServer as any);
logger.warn('warn information');
expect(kbnServer.log.mock.calls[0][0]).toEqual(['warning', APP_ID]);
expect(kbnServer.log.mock.calls[0][1]).toEqual('warn information');
});

test('should log out error', () => {
const kbnServer = createMockServer();
const logger = createLogger(kbnServer as any);
logger.error('error information');
expect(kbnServer.log.mock.calls[0][0]).toEqual(['error', APP_ID]);
expect(kbnServer.log.mock.calls[0][1]).toEqual('error information');
});
});
});
23 changes: 23 additions & 0 deletions x-pack/plugins/secops/server/utils/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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 { Server } from 'hapi';

const LOGGING_TAGS = ['secops'];

export interface Logger {
debug: (message: string) => void;
info: (message: string) => void;
warn: (message: string) => void;
error: (message: string) => void;
}

export const createLogger = (kbnServer: Readonly<Server>): Readonly<Logger> => ({
debug: (message: string) => kbnServer.log(['debug', ...LOGGING_TAGS], message),
info: (message: string) => kbnServer.log(['info', ...LOGGING_TAGS], message),
warn: (message: string) => kbnServer.log(['warning', ...LOGGING_TAGS], message),
error: (message: string) => kbnServer.log(['error', ...LOGGING_TAGS], message),
});