Skip to content

Commit

Permalink
Migrated last pieces of legacy fixture code (elastic#74470)
Browse files Browse the repository at this point in the history
* Migrated last pieces of legacy fixture code

* Implemented own server for webhook simulator

* Fixed type checks. Moved slack simulator to own server

* close server after tests run

* Fixed due to comments

* fixed failing tests
  • Loading branch information
YulNaumenko committed Aug 12, 2020
1 parent 1baa953 commit 7aa9abc
Show file tree
Hide file tree
Showing 14 changed files with 269 additions and 282 deletions.
4 changes: 2 additions & 2 deletions x-pack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@
"cronstrue": "^1.51.0",
"cytoscape": "^3.10.0",
"d3": "3.5.17",
"d3-scale": "1.0.7",
"d3-array": "1.2.4",
"d3-scale": "1.0.7",
"dedent": "^0.7.0",
"del": "^5.1.0",
"dragselect": "1.13.1",
Expand All @@ -268,7 +268,7 @@
"font-awesome": "4.7.0",
"formsy-react": "^1.1.5",
"fp-ts": "^2.3.1",
"get-port": "4.2.0",
"get-port": "^4.2.0",
"getos": "^3.1.0",
"git-url-parse": "11.1.2",
"github-markdown-css": "^2.10.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,25 @@
* you may not use this file except in compliance with the Elastic License.
*/

import http from 'http';
import getPort from 'get-port';
import { FtrProviderContext } from '../../../../common/ftr_provider_context';

import {
getExternalServiceSimulatorPath,
ExternalServiceSimulator,
} from '../../../../common/fixtures/plugins/actions_simulators/server/plugin';
import { getSlackServer } from '../../../../common/fixtures/plugins/actions_simulators/server/plugin';

// eslint-disable-next-line import/no-default-export
export default function slackTest({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const kibanaServer = getService('kibanaServer');

describe('slack action', () => {
let slackSimulatorURL: string = '<could not determine kibana url>';
let slackSimulatorURL: string = '';
let slackServer: http.Server;

// need to wait for kibanaServer to settle ...
before(() => {
slackSimulatorURL = kibanaServer.resolveUrl(
getExternalServiceSimulatorPath(ExternalServiceSimulator.SLACK)
);
before(async () => {
slackServer = await getSlackServer();
const availablePort = await getPort({ port: 9000 });
slackServer.listen(availablePort);
slackSimulatorURL = `http://localhost:${availablePort}`;
});

it('should return 403 when creating a slack action', async () => {
Expand All @@ -44,5 +43,9 @@ export default function slackTest({ getService }: FtrProviderContext) {
'Action type .slack is disabled because your basic license does not support it. Please upgrade your license.',
});
});

after(() => {
slackServer.close();
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,24 @@
* you may not use this file except in compliance with the Elastic License.
*/

import http from 'http';
import getPort from 'get-port';
import { FtrProviderContext } from '../../../../common/ftr_provider_context';
import {
getExternalServiceSimulatorPath,
ExternalServiceSimulator,
} from '../../../../common/fixtures/plugins/actions_simulators/server/plugin';
import { getWebhookServer } from '../../../../common/fixtures/plugins/actions_simulators/server/plugin';

// eslint-disable-next-line import/no-default-export
export default function webhookTest({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const kibanaServer = getService('kibanaServer');

describe('webhook action', () => {
let webhookSimulatorURL: string = '<could not determine kibana url>';

let webhookSimulatorURL: string = '';
let webhookServer: http.Server;
// need to wait for kibanaServer to settle ...
before(() => {
webhookSimulatorURL = kibanaServer.resolveUrl(
getExternalServiceSimulatorPath(ExternalServiceSimulator.WEBHOOK)
);
before(async () => {
webhookServer = await getWebhookServer();
const availablePort = await getPort({ port: 9000 });
webhookServer.listen(availablePort);
webhookSimulatorURL = `http://localhost:${availablePort}`;
});

it('should return 403 when creating a webhook action', async () => {
Expand All @@ -47,5 +46,9 @@ export default function webhookTest({ getService }: FtrProviderContext) {
'Action type .webhook is disabled because your basic license does not support it. Please upgrade your license.',
});
});

after(() => {
webhookServer.close();
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import http from 'http';
import { Plugin, CoreSetup, IRouter } from 'kibana/server';
import { EncryptedSavedObjectsPluginStart } from '../../../../../../../plugins/encrypted_saved_objects/server';
import { PluginSetupContract as FeaturesPluginSetup } from '../../../../../../../plugins/features/server';
Expand All @@ -13,6 +14,8 @@ import { initPlugin as initPagerduty } from './pagerduty_simulation';
import { initPlugin as initServiceNow } from './servicenow_simulation';
import { initPlugin as initJira } from './jira_simulation';
import { initPlugin as initResilient } from './resilient_simulation';
import { initPlugin as initSlack } from './slack_simulation';
import { initPlugin as initWebhook } from './webhook_simulation';

export const NAME = 'actions-FTS-external-service-simulators';

Expand All @@ -39,6 +42,14 @@ export function getAllExternalServiceSimulatorPaths(): string[] {
return allPaths;
}

export async function getWebhookServer(): Promise<http.Server> {
return await initWebhook();
}

export async function getSlackServer(): Promise<http.Server> {
return await initSlack();
}

interface FixtureSetupDeps {
actions: ActionsPluginSetupContract;
features: FeaturesPluginSetup;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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 http from 'http';

export async function initPlugin() {
return http.createServer((request, response) => {
if (request.method === 'POST') {
let data = '';
request.on('data', (chunk) => {
data += chunk;
});
request.on('end', () => {
const body = JSON.parse(data);
const text = body && body.text;

if (text == null) {
response.statusCode = 400;
response.end('bad request to slack simulator');
return;
}

switch (text) {
case 'success': {
response.statusCode = 200;
response.end('ok');
return;
}
case 'no_text':
response.statusCode = 400;
response.end('no_text');
return;

case 'invalid_payload':
response.statusCode = 400;
response.end('invalid_payload');
return;

case 'invalid_token':
response.statusCode = 403;
response.end('invalid_token');
return;

case 'status_500':
response.statusCode = 500;
response.end('simulated slack 500 response');
return;

case 'rate_limit':
const res = {
retry_after: 1,
ok: false,
error: 'rate_limited',
};

response.writeHead(429, { 'Content-Type': 'application/json', 'Retry-After': '1' });
response.write(JSON.stringify(res));
response.end();
return;
}
response.statusCode = 400;
response.end('unknown request to slack simulator');
});
}
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* 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 expect from '@kbn/expect';
import http from 'http';
import { fromNullable, map, filter, getOrElse } from 'fp-ts/lib/Option';
import { pipe } from 'fp-ts/lib/pipeable';
import { constant } from 'fp-ts/lib/function';

export async function initPlugin() {
return http.createServer((request, response) => {
const credentials = pipe(
fromNullable(request.headers.authorization),
map((authorization) => authorization.split(/\s+/)),
filter((parts) => parts.length > 1),
map((parts) => Buffer.from(parts[1], 'base64').toString()),
filter((credentialsPart) => credentialsPart.indexOf(':') !== -1),
map((credentialsPart) => {
const [username, password] = credentialsPart.split(':');
return { username, password };
}),
getOrElse(constant({ username: '', password: '' }))
);

if (request.method === 'POST' || request.method === 'PUT') {
let data = '';
request.on('data', (chunk) => {
data += chunk;
});
request.on('end', () => {
switch (data) {
case 'success':
response.statusCode = 200;
response.end('OK');
return;
case 'authenticate':
return validateAuthentication(credentials, response);
case 'success_post_method':
return validateRequestUsesMethod(request.method ?? '', 'post', response);
case 'success_put_method':
return validateRequestUsesMethod(request.method ?? '', 'put', response);
case 'failure':
response.statusCode = 500;
response.end('Error');
return;
}
response.statusCode = 400;
response.end(
`unknown request to webhook simulator [${data ? `content: ${data}` : `no content`}]`
);
return;
});
} else {
request.on('end', () => {
response.statusCode = 400;
response.end('unknown request to webhook simulator [no content]');
return;
});
}
});
}

function validateAuthentication(credentials: any, res: any) {
try {
expect(credentials).to.eql({
username: 'elastic',
password: 'changeme',
});
res.statusCode = 200;
res.end('OK');
} catch (ex) {
res.statusCode = 403;
res.end(`the validateAuthentication operation failed. ${ex.message}`);
}
}

function validateRequestUsesMethod(requestMethod: string, method: string, res: any) {
try {
expect(requestMethod.toLowerCase()).to.eql(method);
res.statusCode = 200;
res.end('OK');
} catch (ex) {
res.statusCode = 403;
res.end(`the validateAuthentication operation failed. ${ex.message}`);
}
}

This file was deleted.

This file was deleted.

Loading

0 comments on commit 7aa9abc

Please sign in to comment.