From 9432adae5c17a16d676a3c2c3346b0ec945e3e1b Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Thu, 9 Apr 2020 10:36:06 +0200 Subject: [PATCH 01/13] convert api_integration test into TS --- .../apis/logstash/cluster/{index.js => index.ts} | 3 ++- .../apis/logstash/cluster/{load.js => load.ts} | 3 ++- .../api_integration/apis/logstash/{index.js => index.ts} | 3 ++- .../apis/logstash/pipeline/{delete.js => delete.ts} | 3 ++- .../apis/logstash/pipeline/{index.js => index.ts} | 4 ++-- .../apis/logstash/pipeline/{load.js => load.ts} | 6 ++++-- .../apis/logstash/pipeline/{save.js => save.ts} | 3 ++- .../apis/logstash/pipelines/{delete.js => delete.ts} | 3 ++- .../apis/logstash/pipelines/{index.js => index.ts} | 3 ++- .../apis/logstash/pipelines/{list.js => list.ts} | 5 +++-- 10 files changed, 23 insertions(+), 13 deletions(-) rename x-pack/test/api_integration/apis/logstash/cluster/{index.js => index.ts} (71%) rename x-pack/test/api_integration/apis/logstash/cluster/{load.js => load.ts} (83%) rename x-pack/test/api_integration/apis/logstash/{index.js => index.ts} (76%) rename x-pack/test/api_integration/apis/logstash/pipeline/{delete.js => delete.ts} (90%) rename x-pack/test/api_integration/apis/logstash/pipeline/{index.js => index.ts} (76%) rename x-pack/test/api_integration/apis/logstash/pipeline/{load.js => load.ts} (82%) rename x-pack/test/api_integration/apis/logstash/pipeline/{save.js => save.ts} (90%) rename x-pack/test/api_integration/apis/logstash/pipelines/{delete.js => delete.ts} (90%) rename x-pack/test/api_integration/apis/logstash/pipelines/{index.js => index.ts} (73%) rename x-pack/test/api_integration/apis/logstash/pipelines/{list.js => list.ts} (82%) diff --git a/x-pack/test/api_integration/apis/logstash/cluster/index.js b/x-pack/test/api_integration/apis/logstash/cluster/index.ts similarity index 71% rename from x-pack/test/api_integration/apis/logstash/cluster/index.js rename to x-pack/test/api_integration/apis/logstash/cluster/index.ts index f016fde97ee4b..1d4fbd40b252b 100644 --- a/x-pack/test/api_integration/apis/logstash/cluster/index.js +++ b/x-pack/test/api_integration/apis/logstash/cluster/index.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ loadTestFile }) { +export default function({ loadTestFile }: FtrProviderContext) { describe('cluster', () => { loadTestFile(require.resolve('./load')); }); diff --git a/x-pack/test/api_integration/apis/logstash/cluster/load.js b/x-pack/test/api_integration/apis/logstash/cluster/load.ts similarity index 83% rename from x-pack/test/api_integration/apis/logstash/cluster/load.js rename to x-pack/test/api_integration/apis/logstash/cluster/load.ts index a348c6e4857b1..0678c5faf82dc 100644 --- a/x-pack/test/api_integration/apis/logstash/cluster/load.js +++ b/x-pack/test/api_integration/apis/logstash/cluster/load.ts @@ -5,8 +5,9 @@ */ import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ getService }) { +export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const es = getService('legacyEs'); diff --git a/x-pack/test/api_integration/apis/logstash/index.js b/x-pack/test/api_integration/apis/logstash/index.ts similarity index 76% rename from x-pack/test/api_integration/apis/logstash/index.js rename to x-pack/test/api_integration/apis/logstash/index.ts index 53293e5ff9423..582bef5a53bf2 100644 --- a/x-pack/test/api_integration/apis/logstash/index.js +++ b/x-pack/test/api_integration/apis/logstash/index.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { FtrProviderContext } from '../../ftr_provider_context'; -export default function({ loadTestFile }) { +export default function({ loadTestFile }: FtrProviderContext) { describe('logstash', () => { loadTestFile(require.resolve('./pipelines')); loadTestFile(require.resolve('./pipeline')); diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/delete.js b/x-pack/test/api_integration/apis/logstash/pipeline/delete.ts similarity index 90% rename from x-pack/test/api_integration/apis/logstash/pipeline/delete.js rename to x-pack/test/api_integration/apis/logstash/pipeline/delete.ts index 85813f4ed04d1..cdbf5a3e6a1fe 100644 --- a/x-pack/test/api_integration/apis/logstash/pipeline/delete.js +++ b/x-pack/test/api_integration/apis/logstash/pipeline/delete.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ getService }) { +export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); describe('delete', () => { diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/index.js b/x-pack/test/api_integration/apis/logstash/pipeline/index.ts similarity index 76% rename from x-pack/test/api_integration/apis/logstash/pipeline/index.js rename to x-pack/test/api_integration/apis/logstash/pipeline/index.ts index dcc8a01378e37..2697f7f428f5f 100644 --- a/x-pack/test/api_integration/apis/logstash/pipeline/index.js +++ b/x-pack/test/api_integration/apis/logstash/pipeline/index.ts @@ -3,8 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -export default function({ loadTestFile }) { +import { FtrProviderContext } from '../../../ftr_provider_context'; +export default function({ loadTestFile }: FtrProviderContext) { describe('pipeline', () => { loadTestFile(require.resolve('./load')); loadTestFile(require.resolve('./save')); diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/load.js b/x-pack/test/api_integration/apis/logstash/pipeline/load.ts similarity index 82% rename from x-pack/test/api_integration/apis/logstash/pipeline/load.js rename to x-pack/test/api_integration/apis/logstash/pipeline/load.ts index eb2ab6500a9dc..a892f527a6e61 100644 --- a/x-pack/test/api_integration/apis/logstash/pipeline/load.js +++ b/x-pack/test/api_integration/apis/logstash/pipeline/load.ts @@ -5,9 +5,11 @@ */ import expect from '@kbn/expect'; -import pipeline from './fixtures/load'; +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ getService }) { +import pipeline from './fixtures/load.json'; + +export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); describe('list', () => { diff --git a/x-pack/test/api_integration/apis/logstash/pipeline/save.js b/x-pack/test/api_integration/apis/logstash/pipeline/save.ts similarity index 90% rename from x-pack/test/api_integration/apis/logstash/pipeline/save.js rename to x-pack/test/api_integration/apis/logstash/pipeline/save.ts index ad35ee21f00fc..2ca9fbe7d68e0 100644 --- a/x-pack/test/api_integration/apis/logstash/pipeline/save.js +++ b/x-pack/test/api_integration/apis/logstash/pipeline/save.ts @@ -5,8 +5,9 @@ */ import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ getService }) { +export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); describe('save', () => { diff --git a/x-pack/test/api_integration/apis/logstash/pipelines/delete.js b/x-pack/test/api_integration/apis/logstash/pipelines/delete.ts similarity index 90% rename from x-pack/test/api_integration/apis/logstash/pipelines/delete.js rename to x-pack/test/api_integration/apis/logstash/pipelines/delete.ts index 98ff5b99ea744..e71dc7f08ddc9 100644 --- a/x-pack/test/api_integration/apis/logstash/pipelines/delete.js +++ b/x-pack/test/api_integration/apis/logstash/pipelines/delete.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ getService }) { +export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); describe('delete', () => { diff --git a/x-pack/test/api_integration/apis/logstash/pipelines/index.js b/x-pack/test/api_integration/apis/logstash/pipelines/index.ts similarity index 73% rename from x-pack/test/api_integration/apis/logstash/pipelines/index.js rename to x-pack/test/api_integration/apis/logstash/pipelines/index.ts index 3abe2ee5ac43d..510bd625b54a0 100644 --- a/x-pack/test/api_integration/apis/logstash/pipelines/index.js +++ b/x-pack/test/api_integration/apis/logstash/pipelines/index.ts @@ -3,8 +3,9 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { FtrProviderContext } from '../../../ftr_provider_context'; -export default function({ loadTestFile }) { +export default function({ loadTestFile }: FtrProviderContext) { describe('pipelines', () => { loadTestFile(require.resolve('./list')); loadTestFile(require.resolve('./delete')); diff --git a/x-pack/test/api_integration/apis/logstash/pipelines/list.js b/x-pack/test/api_integration/apis/logstash/pipelines/list.ts similarity index 82% rename from x-pack/test/api_integration/apis/logstash/pipelines/list.js rename to x-pack/test/api_integration/apis/logstash/pipelines/list.ts index fe5c3222a2ab1..a4ef52791ab70 100644 --- a/x-pack/test/api_integration/apis/logstash/pipelines/list.js +++ b/x-pack/test/api_integration/apis/logstash/pipelines/list.ts @@ -5,9 +5,10 @@ */ import expect from '@kbn/expect'; -import pipelineList from './fixtures/list'; +import { FtrProviderContext } from '../../../ftr_provider_context'; +import pipelineList from './fixtures/list.json'; -export default function({ getService }) { +export default function({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esArchiver = getService('esArchiver'); describe('list', () => { From f6c9f01beec9774c44ac99d4cb6a99f1dc845bd7 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Thu, 9 Apr 2020 11:22:26 +0200 Subject: [PATCH 02/13] create logstash NP plugin and move models --- .../pipeline_list_item/pipeline_list_item.js | 42 --------------- x-pack/plugins/logstash/kibana.json | 11 ++++ x-pack/plugins/logstash/server/index.ts | 16 ++++++ .../server/models/cluster/cluster.test.ts} | 5 +- .../server/models/cluster/cluster.ts} | 11 ++-- .../logstash/server/models/cluster/index.ts} | 0 .../logstash/server/models/pipeline/index.ts} | 0 .../server/models/pipeline/pipeline.test.ts} | 21 ++++---- .../server/models/pipeline/pipeline.ts} | 54 +++++++++++++------ .../models/pipeline_list_item/index.ts} | 0 .../pipeline_list_item.test.ts} | 13 +++-- .../pipeline_list_item/pipeline_list_item.ts | 52 ++++++++++++++++++ x-pack/plugins/logstash/server/plugin.ts | 28 ++++++++++ .../plugins/logstash/server/routes/index.ts | 7 +++ 14 files changed, 176 insertions(+), 84 deletions(-) delete mode 100755 x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.js create mode 100644 x-pack/plugins/logstash/kibana.json create mode 100644 x-pack/plugins/logstash/server/index.ts rename x-pack/{legacy/plugins/logstash/server/models/cluster/__tests__/cluster.js => plugins/logstash/server/models/cluster/cluster.test.ts} (81%) rename x-pack/{legacy/plugins/logstash/server/models/cluster/cluster.js => plugins/logstash/server/models/cluster/cluster.ts} (68%) rename x-pack/{legacy/plugins/logstash/server/models/cluster/index.js => plugins/logstash/server/models/cluster/index.ts} (100%) rename x-pack/{legacy/plugins/logstash/server/models/pipeline/index.js => plugins/logstash/server/models/pipeline/index.ts} (100%) rename x-pack/{legacy/plugins/logstash/server/models/pipeline/__tests__/pipeline.js => plugins/logstash/server/models/pipeline/pipeline.test.ts} (74%) rename x-pack/{legacy/plugins/logstash/server/models/pipeline/pipeline.js => plugins/logstash/server/models/pipeline/pipeline.ts} (60%) rename x-pack/{legacy/plugins/logstash/server/models/pipeline_list_item/index.js => plugins/logstash/server/models/pipeline_list_item/index.ts} (100%) rename x-pack/{legacy/plugins/logstash/server/models/pipeline_list_item/__tests__/pipeline_list_item.js => plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.test.ts} (73%) create mode 100755 x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.ts create mode 100644 x-pack/plugins/logstash/server/plugin.ts create mode 100644 x-pack/plugins/logstash/server/routes/index.ts diff --git a/x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.js b/x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.js deleted file mode 100755 index bbb506766897e..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 { get } from 'lodash'; - -export class PipelineListItem { - constructor(props) { - this.id = props.id; - this.description = props.description; - this.last_modified = props.last_modified; - this.username = props.username; - } - - get downstreamJSON() { - const json = { - id: this.id, - description: this.description, - last_modified: this.last_modified, - username: this.username, - }; - - return json; - } - - /** - * Takes the json GET response from ES and constructs a pipeline model to be used - * in Kibana downstream - */ - static fromUpstreamJSON(pipeline) { - const opts = { - id: pipeline._id, - description: get(pipeline, '_source.description'), - last_modified: get(pipeline, '_source.last_modified'), - username: get(pipeline, '_source.username'), - }; - - return new PipelineListItem(opts); - } -} diff --git a/x-pack/plugins/logstash/kibana.json b/x-pack/plugins/logstash/kibana.json new file mode 100644 index 0000000000000..54fc57625f53b --- /dev/null +++ b/x-pack/plugins/logstash/kibana.json @@ -0,0 +1,11 @@ +{ + "id": "logstash", + "version": "0.0.1", + "kibanaVersion": "kibana", + "configPath": ["xpack", "logstash"], + "requiredPlugins": [ + "licensing" + ], + "server": true, + "ui": false +} diff --git a/x-pack/plugins/logstash/server/index.ts b/x-pack/plugins/logstash/server/index.ts new file mode 100644 index 0000000000000..cc65184a1f3a0 --- /dev/null +++ b/x-pack/plugins/logstash/server/index.ts @@ -0,0 +1,16 @@ +/* + * 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 { schema } from '@kbn/config-schema'; +import { PluginInitializerContext, PluginConfigDescriptor } from 'src/core/server'; +import { LogstashPlugin } from './plugin'; + +export const plugin = (context: PluginInitializerContext) => new LogstashPlugin(context); + +export const config: PluginConfigDescriptor = { + schema: schema.object({ + enabled: schema.boolean({ defaultValue: true }), + }), +}; diff --git a/x-pack/legacy/plugins/logstash/server/models/cluster/__tests__/cluster.js b/x-pack/plugins/logstash/server/models/cluster/cluster.test.ts similarity index 81% rename from x-pack/legacy/plugins/logstash/server/models/cluster/__tests__/cluster.js rename to x-pack/plugins/logstash/server/models/cluster/cluster.test.ts index 08a447a160a1a..ceb9e2b5d172c 100755 --- a/x-pack/legacy/plugins/logstash/server/models/cluster/__tests__/cluster.js +++ b/x-pack/plugins/logstash/server/models/cluster/cluster.test.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; -import { Cluster } from '../cluster'; +import { Cluster } from './cluster'; describe('cluster', () => { describe('Cluster', () => { @@ -16,7 +15,7 @@ describe('cluster', () => { it('returns correct Cluster instance', () => { const cluster = Cluster.fromUpstreamJSON(upstreamJSON); - expect(cluster.uuid).to.be(upstreamJSON.cluster_uuid); + expect(cluster.downstreamJSON).toEqual({ uuid: upstreamJSON.cluster_uuid }); }); }); }); diff --git a/x-pack/legacy/plugins/logstash/server/models/cluster/cluster.js b/x-pack/plugins/logstash/server/models/cluster/cluster.ts similarity index 68% rename from x-pack/legacy/plugins/logstash/server/models/cluster/cluster.js rename to x-pack/plugins/logstash/server/models/cluster/cluster.ts index b114162fb0986..c33398a1c6f13 100755 --- a/x-pack/legacy/plugins/logstash/server/models/cluster/cluster.js +++ b/x-pack/plugins/logstash/server/models/cluster/cluster.ts @@ -10,11 +10,12 @@ import { get } from 'lodash'; * This model deals with a cluster object from ES and converts it to Kibana downstream */ export class Cluster { - constructor(props) { - this.uuid = props.uuid; + private readonly uuid: string; + constructor({ uuid }: { uuid: string }) { + this.uuid = uuid; } - get downstreamJSON() { + public get downstreamJSON() { const json = { uuid: this.uuid, }; @@ -23,8 +24,8 @@ export class Cluster { } // generate Pipeline object from elasticsearch response - static fromUpstreamJSON(upstreamCluster) { - const uuid = get(upstreamCluster, 'cluster_uuid'); + static fromUpstreamJSON(upstreamCluster: Record) { + const uuid = get(upstreamCluster, 'cluster_uuid'); return new Cluster({ uuid }); } } diff --git a/x-pack/legacy/plugins/logstash/server/models/cluster/index.js b/x-pack/plugins/logstash/server/models/cluster/index.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/server/models/cluster/index.js rename to x-pack/plugins/logstash/server/models/cluster/index.ts diff --git a/x-pack/legacy/plugins/logstash/server/models/pipeline/index.js b/x-pack/plugins/logstash/server/models/pipeline/index.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/server/models/pipeline/index.js rename to x-pack/plugins/logstash/server/models/pipeline/index.ts diff --git a/x-pack/legacy/plugins/logstash/server/models/pipeline/__tests__/pipeline.js b/x-pack/plugins/logstash/server/models/pipeline/pipeline.test.ts similarity index 74% rename from x-pack/legacy/plugins/logstash/server/models/pipeline/__tests__/pipeline.js rename to x-pack/plugins/logstash/server/models/pipeline/pipeline.test.ts index 41869c22271f0..82ce0d72e2052 100755 --- a/x-pack/legacy/plugins/logstash/server/models/pipeline/__tests__/pipeline.js +++ b/x-pack/plugins/logstash/server/models/pipeline/pipeline.test.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; -import { Pipeline } from '../pipeline'; +import { Pipeline } from './pipeline'; describe('pipeline', () => { describe('Pipeline', () => { @@ -25,10 +24,10 @@ describe('pipeline', () => { it('returns correct Pipeline instance', () => { const pipeline = Pipeline.fromUpstreamJSON(upstreamJSON); - expect(pipeline.id).to.be(upstreamJSON._id); - expect(pipeline.description).to.be(upstreamJSON._source.description); - expect(pipeline.username).to.be(upstreamJSON._source.username); - expect(pipeline.pipeline).to.be(upstreamJSON._source.pipeline); + expect(pipeline.id).toBe(upstreamJSON._id); + expect(pipeline.description).toBe(upstreamJSON._source.description); + expect(pipeline.username).toBe(upstreamJSON._source.username); + expect(pipeline.pipeline).toBe(upstreamJSON._source.pipeline); }); it('throws if pipeline argument does not contain an id property', () => { @@ -39,7 +38,7 @@ describe('pipeline', () => { const testFromUpstreamJsonError = () => { return Pipeline.fromUpstreamJSON(badJSON); }; - expect(testFromUpstreamJsonError).to.throwError( + expect(testFromUpstreamJsonError).toThrowError( /upstreamPipeline argument must contain an id property/i ); }); @@ -64,12 +63,12 @@ describe('pipeline', () => { pipeline: 'input {} filter { grok {} }\n output {}', }; // can't do an object level comparison because modified field is always `now` - expect(pipeline.upstreamJSON.last_modified).to.be.a('string'); - expect(pipeline.upstreamJSON.description).to.be(expectedUpstreamJSON.description); - expect(pipeline.upstreamJSON.pipeline_metadata).to.eql( + expect(pipeline.upstreamJSON.last_modified).toStrictEqual(expect.any(String)); + expect(pipeline.upstreamJSON.description).toBe(expectedUpstreamJSON.description); + expect(pipeline.upstreamJSON.pipeline_metadata).toEqual( expectedUpstreamJSON.pipeline_metadata ); - expect(pipeline.upstreamJSON.pipeline).to.be(expectedUpstreamJSON.pipeline); + expect(pipeline.upstreamJSON.pipeline).toBe(expectedUpstreamJSON.pipeline); }); }); }); diff --git a/x-pack/legacy/plugins/logstash/server/models/pipeline/pipeline.js b/x-pack/plugins/logstash/server/models/pipeline/pipeline.ts similarity index 60% rename from x-pack/legacy/plugins/logstash/server/models/pipeline/pipeline.js rename to x-pack/plugins/logstash/server/models/pipeline/pipeline.ts index f02d303cb0380..f28af33597e64 100755 --- a/x-pack/legacy/plugins/logstash/server/models/pipeline/pipeline.js +++ b/x-pack/plugins/logstash/server/models/pipeline/pipeline.ts @@ -9,19 +9,37 @@ import { badRequest } from 'boom'; import { get } from 'lodash'; import { i18n } from '@kbn/i18n'; +interface PipelineOptions { + id: string; + description: string; + username: string; + pipeline: string; + settings?: Record; +} + +interface DownstreamPipeline { + description: string; + pipeline: string; + settings: Record; +} /** * This model deals with a pipeline object from ES and converts it to Kibana downstream */ export class Pipeline { - constructor(props) { - this.id = props.id; - this.description = props.description; - this.username = props.username; - this.pipeline = props.pipeline; - this.settings = props.settings || {}; + public readonly id: string; + public readonly description: string; + public readonly username: string; + public readonly pipeline: string; + private readonly settings: Record; + constructor(options: PipelineOptions) { + this.id = options.id; + this.description = options.description; + this.username = options.username; + this.pipeline = options.pipeline; + this.settings = options.settings || {}; } - get downstreamJSON() { + public get downstreamJSON() { const json = { id: this.id, description: this.description, @@ -41,7 +59,7 @@ export class Pipeline { * pipeline_metadata.type is the Logstash config type (future: LIR, json, etc) * @return {[JSON]} [Elasticsearch JSON] */ - get upstreamJSON() { + public get upstreamJSON() { return { description: this.description, last_modified: moment().toISOString(), @@ -56,7 +74,11 @@ export class Pipeline { } // generate Pipeline object from kibana response - static fromDownstreamJSON(downstreamPipeline, pipelineId, username) { + static fromDownstreamJSON( + downstreamPipeline: DownstreamPipeline, + pipelineId: string, + username: string + ) { const opts = { id: pipelineId, description: downstreamPipeline.description, @@ -69,7 +91,7 @@ export class Pipeline { } // generate Pipeline object from elasticsearch response - static fromUpstreamJSON(upstreamPipeline) { + static fromUpstreamJSON(upstreamPipeline: Record) { if (!upstreamPipeline._id) { throw badRequest( i18n.translate( @@ -80,13 +102,13 @@ export class Pipeline { ) ); } - const id = get(upstreamPipeline, '_id'); - const description = get(upstreamPipeline, '_source.description'); - const username = get(upstreamPipeline, '_source.username'); - const pipeline = get(upstreamPipeline, '_source.pipeline'); - const settings = get(upstreamPipeline, '_source.pipeline_settings'); + const id = get(upstreamPipeline, '_id'); + const description = get(upstreamPipeline, '_source.description'); + const username = get(upstreamPipeline, '_source.username'); + const pipeline = get(upstreamPipeline, '_source.pipeline'); + const settings = get>(upstreamPipeline, '_source.pipeline_settings'); - const opts = { id, description, username, pipeline, settings }; + const opts: PipelineOptions = { id, description, username, pipeline, settings }; return new Pipeline(opts); } diff --git a/x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/index.js b/x-pack/plugins/logstash/server/models/pipeline_list_item/index.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/index.js rename to x-pack/plugins/logstash/server/models/pipeline_list_item/index.ts diff --git a/x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/__tests__/pipeline_list_item.js b/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.test.ts similarity index 73% rename from x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/__tests__/pipeline_list_item.js rename to x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.test.ts index 4f3a447f030c7..f909e90ce43ca 100755 --- a/x-pack/legacy/plugins/logstash/server/models/pipeline_list_item/__tests__/pipeline_list_item.js +++ b/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.test.ts @@ -4,8 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import expect from '@kbn/expect'; -import { PipelineListItem } from '../pipeline_list_item'; +import { PipelineListItem } from './pipeline_list_item'; describe('pipeline_list_item', () => { describe('PipelineListItem', () => { @@ -26,10 +25,10 @@ describe('pipeline_list_item', () => { describe('fromUpstreamJSON factory method', () => { it('returns correct PipelineListItem instance', () => { const pipelineListItem = PipelineListItem.fromUpstreamJSON(upstreamJSON); - expect(pipelineListItem.id).to.be(upstreamJSON._id); - expect(pipelineListItem.description).to.be(upstreamJSON._source.description); - expect(pipelineListItem.username).to.be(upstreamJSON._source.username); - expect(pipelineListItem.last_modified).to.be(upstreamJSON._source.last_modified); + expect(pipelineListItem.id).toBe(upstreamJSON._id); + expect(pipelineListItem.description).toBe(upstreamJSON._source.description); + expect(pipelineListItem.username).toBe(upstreamJSON._source.username); + expect(pipelineListItem.last_modified).toBe(upstreamJSON._source.last_modified); }); }); @@ -42,7 +41,7 @@ describe('pipeline_list_item', () => { username: 'elastic', last_modified: '2017-05-14T02:50:51.250Z', }; - expect(pipelineListItem.downstreamJSON).to.eql(expectedDownstreamJSON); + expect(pipelineListItem.downstreamJSON).toEqual(expectedDownstreamJSON); }); }); }); diff --git a/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.ts b/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.ts new file mode 100755 index 0000000000000..68f91934adf43 --- /dev/null +++ b/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.ts @@ -0,0 +1,52 @@ +/* + * 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 { get } from 'lodash'; + +interface PipelineListItemOptions { + id: string; + description: string; + last_modified: string; + username: string; +} +export class PipelineListItem { + private readonly id: string; + private readonly description: string; + private readonly last_modified: string; + private readonly username: string; + constructor(options: PipelineListItemOptions) { + this.id = options.id; + this.description = options.description; + this.last_modified = options.last_modified; + this.username = options.username; + } + + public get downstreamJSON() { + const json = { + id: this.id, + description: this.description, + last_modified: this.last_modified, + username: this.username, + }; + + return json; + } + + /** + * Takes the json GET response from ES and constructs a pipeline model to be used + * in Kibana downstream + */ + static fromUpstreamJSON(pipeline: Record) { + const opts = { + id: pipeline._id, + description: get(pipeline, '_source.description'), + last_modified: get(pipeline, '_source.last_modified'), + username: get(pipeline, '_source.username'), + }; + + return new PipelineListItem(opts); + } +} diff --git a/x-pack/plugins/logstash/server/plugin.ts b/x-pack/plugins/logstash/server/plugin.ts new file mode 100644 index 0000000000000..903d885c4ecd9 --- /dev/null +++ b/x-pack/plugins/logstash/server/plugin.ts @@ -0,0 +1,28 @@ +/* + * 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 { CoreSetup, Logger, Plugin, PluginInitializerContext } from 'src/core/server'; +import { LicensingPluginSetup } from '../../licensing/server'; + +import { registerRoutes } from './routes'; + +interface SetupDeps { + licensing: LicensingPluginSetup; +} + +export class LogstashPlugin implements Plugin { + private readonly logger: Logger; + constructor(context: PluginInitializerContext) { + this.logger = context.logger.get(); + } + + setup(core: CoreSetup, deps: SetupDeps) { + this.logger.debug('Setting up Logstash plugin'); + registerRoutes(core.http.createRouter()); + } + + start() {} + stop() {} +} diff --git a/x-pack/plugins/logstash/server/routes/index.ts b/x-pack/plugins/logstash/server/routes/index.ts new file mode 100644 index 0000000000000..6dac28828a1ea --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/index.ts @@ -0,0 +1,7 @@ +/* + * 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 { IRouter } from 'src/core/server'; +export function registerRoutes(router: IRouter) {} From b8e114ed8cf375cc06727eadde6ca531fe98e0bc Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Thu, 9 Apr 2020 12:01:57 +0200 Subject: [PATCH 03/13] move common/constants to NP --- x-pack/legacy/plugins/logstash/index.js | 2 +- .../pipeline_editor/pipeline_editor.js | 2 +- .../public/lib/register_home_feature.ts | 2 +- .../pipeline_list_item/pipeline_list_item.js | 2 +- .../services/cluster/cluster_service.js | 2 +- .../license/logstash_license_service.js | 2 +- .../services/monitoring/monitoring_service.js | 2 +- .../services/pipeline/pipeline_service.js | 2 +- .../services/pipelines/pipelines_service.js | 2 +- .../services/upgrade/upgrade_service.js | 2 +- .../__tests__/fetch_all_from_scroll.js | 88 ------------------- .../license_pre_routing_factory.js | 2 +- .../register_license_checker.js | 2 +- .../api/pipeline/register_delete_route.js | 2 +- .../api/pipeline/register_load_route.js | 5 +- .../api/pipeline/register_save_route.js | 5 +- .../api/pipelines/register_delete_route.js | 2 +- .../api/pipelines/register_list_route.js | 11 ++- .../api/upgrade/register_execute_route.js | 2 +- .../common/constants/es_scroll_settings.ts} | 0 .../logstash/common/constants/index.ts} | 0 .../logstash/common/constants/index_names.ts} | 0 .../logstash/common/constants/monitoring.ts} | 0 .../logstash/common/constants/pagination.ts} | 0 .../logstash/common/constants/pipeline.ts} | 0 .../logstash/common/constants/plugin.ts} | 0 .../logstash/common/constants/routes.ts} | 0 .../logstash/common/constants/tooltips.ts} | 0 .../fetch_all_from_scroll.test.ts | 72 +++++++++++++++ .../fetch_all_from_scroll.ts} | 8 +- .../lib/fetch_all_from_scroll/index.ts} | 0 31 files changed, 107 insertions(+), 112 deletions(-) delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js rename x-pack/{legacy/plugins/logstash/common/constants/es_scroll_settings.js => plugins/logstash/common/constants/es_scroll_settings.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/index.js => plugins/logstash/common/constants/index.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/index_names.js => plugins/logstash/common/constants/index_names.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/monitoring.js => plugins/logstash/common/constants/monitoring.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/pagination.js => plugins/logstash/common/constants/pagination.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/pipeline.js => plugins/logstash/common/constants/pipeline.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/plugin.js => plugins/logstash/common/constants/plugin.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/routes.js => plugins/logstash/common/constants/routes.ts} (100%) rename x-pack/{legacy/plugins/logstash/common/constants/tooltips.js => plugins/logstash/common/constants/tooltips.ts} (100%) create mode 100755 x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.ts rename x-pack/{legacy/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.js => plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts} (81%) rename x-pack/{legacy/plugins/logstash/server/lib/fetch_all_from_scroll/index.js => plugins/logstash/server/lib/fetch_all_from_scroll/index.ts} (100%) diff --git a/x-pack/legacy/plugins/logstash/index.js b/x-pack/legacy/plugins/logstash/index.js index ae8571d1c19c3..fcabcd78705b1 100755 --- a/x-pack/legacy/plugins/logstash/index.js +++ b/x-pack/legacy/plugins/logstash/index.js @@ -10,7 +10,7 @@ import { registerLogstashPipelineRoutes } from './server/routes/api/pipeline'; import { registerLogstashUpgradeRoutes } from './server/routes/api/upgrade'; import { registerLogstashClusterRoutes } from './server/routes/api/cluster'; import { registerLicenseChecker } from './server/lib/register_license_checker'; -import { PLUGIN } from './common/constants'; +import { PLUGIN } from '../../../plugins/logstash/common/constants'; export const logstash = kibana => new kibana.Plugin({ diff --git a/x-pack/legacy/plugins/logstash/public/components/pipeline_editor/pipeline_editor.js b/x-pack/legacy/plugins/logstash/public/components/pipeline_editor/pipeline_editor.js index 43ca656e0827c..5e430ccbd8ceb 100644 --- a/x-pack/legacy/plugins/logstash/public/components/pipeline_editor/pipeline_editor.js +++ b/x-pack/legacy/plugins/logstash/public/components/pipeline_editor/pipeline_editor.js @@ -13,7 +13,7 @@ import 'brace/mode/plain_text'; import 'brace/theme/github'; import { isEmpty } from 'lodash'; -import { TOOLTIPS } from '../../../common/constants/tooltips'; +import { TOOLTIPS } from '../../../../../../plugins/logstash/common/constants/tooltips'; import { EuiButton, EuiButtonEmpty, diff --git a/x-pack/legacy/plugins/logstash/public/lib/register_home_feature.ts b/x-pack/legacy/plugins/logstash/public/lib/register_home_feature.ts index e943656120d5e..2e1ee2afb9ce6 100644 --- a/x-pack/legacy/plugins/logstash/public/lib/register_home_feature.ts +++ b/x-pack/legacy/plugins/logstash/public/lib/register_home_feature.ts @@ -10,7 +10,7 @@ import { npSetup } from 'ui/new_platform'; import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; import { FeatureCatalogueCategory } from '../../../../../../src/plugins/home/public'; // @ts-ignore -import { PLUGIN } from '../../common/constants'; +import { PLUGIN } from '../../../../../plugins/logstash/common/constants'; const { plugins: { home }, diff --git a/x-pack/legacy/plugins/logstash/public/models/pipeline_list_item/pipeline_list_item.js b/x-pack/legacy/plugins/logstash/public/models/pipeline_list_item/pipeline_list_item.js index 14900fdaa7cdc..06d01a05bac27 100755 --- a/x-pack/legacy/plugins/logstash/public/models/pipeline_list_item/pipeline_list_item.js +++ b/x-pack/legacy/plugins/logstash/public/models/pipeline_list_item/pipeline_list_item.js @@ -8,7 +8,7 @@ import { pick, capitalize } from 'lodash'; import { getSearchValue } from 'plugins/logstash/lib/get_search_value'; import { getMoment } from 'plugins/logstash/../common/lib/get_moment'; -import { PIPELINE } from '../../../common/constants'; +import { PIPELINE } from '../../../../../../plugins/logstash/common/constants'; /** * Represents the model for listing pipelines in the UI diff --git a/x-pack/legacy/plugins/logstash/public/services/cluster/cluster_service.js b/x-pack/legacy/plugins/logstash/public/services/cluster/cluster_service.js index 4bad4f48cc61d..e89c2fe7d11bf 100755 --- a/x-pack/legacy/plugins/logstash/public/services/cluster/cluster_service.js +++ b/x-pack/legacy/plugins/logstash/public/services/cluster/cluster_service.js @@ -5,7 +5,7 @@ */ import chrome from 'ui/chrome'; -import { ROUTES } from '../../../common/constants'; +import { ROUTES } from '../../../../../../plugins/logstash/common/constants'; import { Cluster } from 'plugins/logstash/models/cluster'; export class ClusterService { diff --git a/x-pack/legacy/plugins/logstash/public/services/license/logstash_license_service.js b/x-pack/legacy/plugins/logstash/public/services/license/logstash_license_service.js index 97b336ec0728b..69cc8614a6ae2 100755 --- a/x-pack/legacy/plugins/logstash/public/services/license/logstash_license_service.js +++ b/x-pack/legacy/plugins/logstash/public/services/license/logstash_license_service.js @@ -7,7 +7,7 @@ import React from 'react'; import { toastNotifications } from 'ui/notify'; import { MarkdownSimple } from '../../../../../../../src/plugins/kibana_react/public'; -import { PLUGIN } from '../../../common/constants'; +import { PLUGIN } from '../../../../../../plugins/logstash/common/constants'; export class LogstashLicenseService { constructor(xpackInfoService, kbnUrlService, $timeout) { diff --git a/x-pack/legacy/plugins/logstash/public/services/monitoring/monitoring_service.js b/x-pack/legacy/plugins/logstash/public/services/monitoring/monitoring_service.js index 8a267e38db738..6103e730c2171 100755 --- a/x-pack/legacy/plugins/logstash/public/services/monitoring/monitoring_service.js +++ b/x-pack/legacy/plugins/logstash/public/services/monitoring/monitoring_service.js @@ -6,7 +6,7 @@ import moment from 'moment'; import chrome from 'ui/chrome'; -import { ROUTES, MONITORING } from '../../../common/constants'; +import { ROUTES, MONITORING } from '../../../../../../plugins/logstash/common/constants'; import { PipelineListItem } from 'plugins/logstash/models/pipeline_list_item'; export class MonitoringService { diff --git a/x-pack/legacy/plugins/logstash/public/services/pipeline/pipeline_service.js b/x-pack/legacy/plugins/logstash/public/services/pipeline/pipeline_service.js index 0696bf9d83256..b5d0dbeb852d5 100755 --- a/x-pack/legacy/plugins/logstash/public/services/pipeline/pipeline_service.js +++ b/x-pack/legacy/plugins/logstash/public/services/pipeline/pipeline_service.js @@ -5,7 +5,7 @@ */ import chrome from 'ui/chrome'; -import { ROUTES } from '../../../common/constants'; +import { ROUTES } from '../../../../../../plugins/logstash/common/constants'; import { Pipeline } from 'plugins/logstash/models/pipeline'; export class PipelineService { diff --git a/x-pack/legacy/plugins/logstash/public/services/pipelines/pipelines_service.js b/x-pack/legacy/plugins/logstash/public/services/pipelines/pipelines_service.js index 5a43cf07eba41..d70c8be06fde4 100755 --- a/x-pack/legacy/plugins/logstash/public/services/pipelines/pipelines_service.js +++ b/x-pack/legacy/plugins/logstash/public/services/pipelines/pipelines_service.js @@ -5,7 +5,7 @@ */ import chrome from 'ui/chrome'; -import { ROUTES, MONITORING } from '../../../common/constants'; +import { ROUTES, MONITORING } from '../../../../../../plugins/logstash/common/constants'; import { PipelineListItem } from 'plugins/logstash/models/pipeline_list_item'; const RECENTLY_DELETED_PIPELINE_IDS_STORAGE_KEY = 'xpack.logstash.recentlyDeletedPipelines'; diff --git a/x-pack/legacy/plugins/logstash/public/services/upgrade/upgrade_service.js b/x-pack/legacy/plugins/logstash/public/services/upgrade/upgrade_service.js index 7870a495d07a3..2019bdc1bf1aa 100755 --- a/x-pack/legacy/plugins/logstash/public/services/upgrade/upgrade_service.js +++ b/x-pack/legacy/plugins/logstash/public/services/upgrade/upgrade_service.js @@ -5,7 +5,7 @@ */ import chrome from 'ui/chrome'; -import { ROUTES } from '../../../common/constants'; +import { ROUTES } from '../../../../../../plugins/logstash/common/constants'; export class UpgradeService { constructor($http) { diff --git a/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js b/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js deleted file mode 100755 index b1593fb1ba355..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/__tests__/fetch_all_from_scroll.js +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 sinon from 'sinon'; -import { fetchAllFromScroll } from '../fetch_all_from_scroll'; -import { set } from 'lodash'; - -describe('fetch_all_from_scroll', () => { - let mockResponse; - let stubCallWithRequest; - - beforeEach(() => { - mockResponse = {}; - - stubCallWithRequest = sinon.stub(); - stubCallWithRequest.onCall(0).returns( - new Promise(resolve => { - const mockInnerResponse = { - hits: { - hits: ['newhit'], - }, - _scroll_id: 'newScrollId', - }; - return resolve(mockInnerResponse); - }) - ); - - stubCallWithRequest.onCall(1).returns( - new Promise(resolve => { - const mockInnerResponse = { - hits: { - hits: [], - }, - }; - return resolve(mockInnerResponse); - }) - ); - }); - - describe('#fetchAllFromScroll', () => { - describe('when the passed-in response has no hits', () => { - beforeEach(() => { - set(mockResponse, 'hits.hits', []); - }); - - it('should return an empty array of hits', () => { - return fetchAllFromScroll(mockResponse).then(hits => { - expect(hits).to.eql([]); - }); - }); - - it('should not call callWithRequest', () => { - return fetchAllFromScroll(mockResponse, stubCallWithRequest).then(() => { - expect(stubCallWithRequest.called).to.be(false); - }); - }); - }); - - describe('when the passed-in response has some hits', () => { - beforeEach(() => { - set(mockResponse, 'hits.hits', ['foo', 'bar']); - set(mockResponse, '_scroll_id', 'originalScrollId'); - }); - - it('should return the hits from the response', () => { - return fetchAllFromScroll(mockResponse, stubCallWithRequest).then(hits => { - expect(hits).to.eql(['foo', 'bar', 'newhit']); - }); - }); - - it('should call callWithRequest', () => { - return fetchAllFromScroll(mockResponse, stubCallWithRequest).then(() => { - expect(stubCallWithRequest.calledTwice).to.be(true); - - const firstCallWithRequestCallArgs = stubCallWithRequest.args[0]; - expect(firstCallWithRequestCallArgs[1].body.scroll_id).to.eql('originalScrollId'); - - const secondCallWithRequestCallArgs = stubCallWithRequest.args[1]; - expect(secondCallWithRequestCallArgs[1].body.scroll_id).to.eql('newScrollId'); - }); - }); - }); - }); -}); diff --git a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js b/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js index 05402a56a52d8..461fb0846eca8 100755 --- a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js +++ b/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js @@ -6,7 +6,7 @@ import { once } from 'lodash'; import { wrapCustomError } from '../error_wrappers'; -import { PLUGIN } from '../../../common/constants'; +import { PLUGIN } from '../../../../../../plugins/logstash/common/constants'; export const licensePreRoutingFactory = once(server => { const xpackMainPlugin = server.plugins.xpack_main; diff --git a/x-pack/legacy/plugins/logstash/server/lib/register_license_checker/register_license_checker.js b/x-pack/legacy/plugins/logstash/server/lib/register_license_checker/register_license_checker.js index 8a17fb2eea497..a0d06e77b410d 100755 --- a/x-pack/legacy/plugins/logstash/server/lib/register_license_checker/register_license_checker.js +++ b/x-pack/legacy/plugins/logstash/server/lib/register_license_checker/register_license_checker.js @@ -6,7 +6,7 @@ import { mirrorPluginStatus } from '../../../../../server/lib/mirror_plugin_status'; import { checkLicense } from '../check_license'; -import { PLUGIN } from '../../../common/constants'; +import { PLUGIN } from '../../../../../../plugins/logstash/common/constants'; export function registerLicenseChecker(server) { const xpackMainPlugin = server.plugins.xpack_main; diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_delete_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_delete_route.js index 232ee4207541c..42c77a4444249 100755 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_delete_route.js +++ b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_delete_route.js @@ -6,7 +6,7 @@ import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; import { wrapEsError } from '../../../lib/error_wrappers'; -import { INDEX_NAMES } from '../../../../common/constants'; +import { INDEX_NAMES } from '../../../../../../../plugins/logstash/common/constants'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; function deletePipeline(callWithRequest, pipelineId) { diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_load_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_load_route.js index 796bf939d747f..6a385614ed99c 100755 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_load_route.js +++ b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_load_route.js @@ -5,9 +5,10 @@ */ import Boom from 'boom'; -import { INDEX_NAMES } from '../../../../common/constants'; +import { INDEX_NAMES } from '../../../../../../../plugins/logstash/common/constants'; import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { Pipeline } from '../../../models/pipeline'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { Pipeline } from '../../../../../../../plugins/logstash/server/models/pipeline'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; function fetchPipeline(callWithRequest, pipelineId) { diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_save_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_save_route.js index 50f62dc0a0ddd..87b56bd84584c 100755 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_save_route.js +++ b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_save_route.js @@ -6,9 +6,10 @@ import { get } from 'lodash'; import { wrapEsError } from '../../../lib/error_wrappers'; -import { INDEX_NAMES } from '../../../../common/constants'; +import { INDEX_NAMES } from '../../../../../../../plugins/logstash/common/constants'; import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { Pipeline } from '../../../models/pipeline'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { Pipeline } from '../../../../../../../plugins/logstash/server/models/pipeline'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; function savePipeline(callWithRequest, pipelineId, pipelineBody) { diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_delete_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_delete_route.js index 8ccd792d5a876..637e8ea8d5c38 100755 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_delete_route.js +++ b/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_delete_route.js @@ -6,7 +6,7 @@ import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; import { wrapUnknownError } from '../../../lib/error_wrappers'; -import { INDEX_NAMES } from '../../../../common/constants'; +import { INDEX_NAMES } from '../../../../../../../plugins/logstash/common/constants'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; function deletePipelines(callWithRequest, pipelineIds) { diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_list_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_list_route.js index 43ce1c3e8f6f6..16446e2204db8 100755 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_list_route.js +++ b/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_list_route.js @@ -6,9 +6,14 @@ import { wrapEsError } from '../../../lib/error_wrappers'; import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { fetchAllFromScroll } from '../../../lib/fetch_all_from_scroll'; -import { INDEX_NAMES, ES_SCROLL_SETTINGS } from '../../../../common/constants'; -import { PipelineListItem } from '../../../models/pipeline_list_item'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { fetchAllFromScroll } from '../../../../../../../plugins/logstash/server/lib/fetch_all_from_scroll'; +import { + INDEX_NAMES, + ES_SCROLL_SETTINGS, +} from '../../../../../../../plugins/logstash/common/constants'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { PipelineListItem } from '../../../../../../../plugins/logstash/server/models/pipeline_list_item'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; function fetchPipelines(callWithRequest) { diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_execute_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_execute_route.js index 16f97930ae25e..62e60a99d2eea 100755 --- a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_execute_route.js +++ b/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_execute_route.js @@ -6,7 +6,7 @@ import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; import { wrapUnknownError } from '../../../lib/error_wrappers'; -import { INDEX_NAMES } from '../../../../common/constants'; +import { INDEX_NAMES } from '../../../../../../../plugins/logstash/common/constants'; import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; function doesIndexExist(callWithRequest) { diff --git a/x-pack/legacy/plugins/logstash/common/constants/es_scroll_settings.js b/x-pack/plugins/logstash/common/constants/es_scroll_settings.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/es_scroll_settings.js rename to x-pack/plugins/logstash/common/constants/es_scroll_settings.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/index.js b/x-pack/plugins/logstash/common/constants/index.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/index.js rename to x-pack/plugins/logstash/common/constants/index.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/index_names.js b/x-pack/plugins/logstash/common/constants/index_names.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/index_names.js rename to x-pack/plugins/logstash/common/constants/index_names.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/monitoring.js b/x-pack/plugins/logstash/common/constants/monitoring.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/monitoring.js rename to x-pack/plugins/logstash/common/constants/monitoring.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/pagination.js b/x-pack/plugins/logstash/common/constants/pagination.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/pagination.js rename to x-pack/plugins/logstash/common/constants/pagination.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/pipeline.js b/x-pack/plugins/logstash/common/constants/pipeline.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/pipeline.js rename to x-pack/plugins/logstash/common/constants/pipeline.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/plugin.js b/x-pack/plugins/logstash/common/constants/plugin.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/plugin.js rename to x-pack/plugins/logstash/common/constants/plugin.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/routes.js b/x-pack/plugins/logstash/common/constants/routes.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/routes.js rename to x-pack/plugins/logstash/common/constants/routes.ts diff --git a/x-pack/legacy/plugins/logstash/common/constants/tooltips.js b/x-pack/plugins/logstash/common/constants/tooltips.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/common/constants/tooltips.js rename to x-pack/plugins/logstash/common/constants/tooltips.ts diff --git a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.ts b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.ts new file mode 100755 index 0000000000000..df3f4f6756648 --- /dev/null +++ b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.ts @@ -0,0 +1,72 @@ +/* + * 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 { fetchAllFromScroll } from './fetch_all_from_scroll'; + +describe('fetch_all_from_scroll', () => { + let stubCallWithRequest: jest.Mock; + + beforeEach(() => { + stubCallWithRequest = jest.fn(); + stubCallWithRequest + .mockResolvedValueOnce({ + hits: { + hits: ['newhit'], + }, + _scroll_id: 'newScrollId', + }) + .mockResolvedValueOnce({ + hits: { + hits: [], + }, + }); + }); + + describe('#fetchAllFromScroll', () => { + describe('when the passed-in response has no hits', () => { + const mockResponse = { + hits: { + hits: [], + }, + }; + + it('should return an empty array of hits', async () => { + const hits = await fetchAllFromScroll(mockResponse, stubCallWithRequest); + expect(hits).toEqual([]); + }); + + it('should not call callWithRequest', async () => { + await fetchAllFromScroll(mockResponse, stubCallWithRequest); + expect(stubCallWithRequest).toHaveBeenCalledTimes(0); + }); + }); + + describe('when the passed-in response has some hits', () => { + const mockResponse = { + hits: { + hits: ['foo', 'bar'], + }, + _scroll_id: 'originalScrollId', + }; + + it('should return the hits from the response', async () => { + const hits = await fetchAllFromScroll(mockResponse, stubCallWithRequest); + expect(hits).toEqual(['foo', 'bar', 'newhit']); + }); + + it('should call callWithRequest', async () => { + await fetchAllFromScroll(mockResponse, stubCallWithRequest); + expect(stubCallWithRequest).toHaveBeenCalledTimes(2); + + const firstCallWithRequestCallArgs = stubCallWithRequest.mock.calls[0]; + expect(firstCallWithRequestCallArgs[1].body.scroll_id).toBe('originalScrollId'); + + const secondCallWithRequestCallArgs = stubCallWithRequest.mock.calls[1]; + expect(secondCallWithRequestCallArgs[1].body.scroll_id).toBe('newScrollId'); + }); + }); + }); +}); diff --git a/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.js b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts similarity index 81% rename from x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.js rename to x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts index 835ef0090a5d2..779b160db7ee5 100755 --- a/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.js +++ b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts @@ -3,11 +3,15 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import { APICaller } from 'src/core/server'; import { get } from 'lodash'; import { ES_SCROLL_SETTINGS } from '../../../common/constants'; -export function fetchAllFromScroll(response, callWithRequest, hits = []) { +export function fetchAllFromScroll( + response: Record, + callWithRequest: APICaller, + hits = [] +): Record { const newHits = get(response, 'hits.hits', []); const scrollId = get(response, '_scroll_id'); diff --git a/x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/index.js b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/index.ts similarity index 100% rename from x-pack/legacy/plugins/logstash/server/lib/fetch_all_from_scroll/index.js rename to x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/index.ts From fcca07db4cc409501bab339dedc112d6351d8475 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Thu, 9 Apr 2020 12:11:47 +0200 Subject: [PATCH 04/13] type fetch all from scroll --- .../fetch_all_from_scroll.test.ts | 9 ++++--- .../fetch_all_from_scroll.ts | 24 ++++++++++--------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.ts b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.ts index df3f4f6756648..8cd6b70d47570 100755 --- a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.ts +++ b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.ts @@ -3,7 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - import { fetchAllFromScroll } from './fetch_all_from_scroll'; describe('fetch_all_from_scroll', () => { @@ -34,12 +33,12 @@ describe('fetch_all_from_scroll', () => { }; it('should return an empty array of hits', async () => { - const hits = await fetchAllFromScroll(mockResponse, stubCallWithRequest); + const hits = await fetchAllFromScroll(mockResponse as any, stubCallWithRequest); expect(hits).toEqual([]); }); it('should not call callWithRequest', async () => { - await fetchAllFromScroll(mockResponse, stubCallWithRequest); + await fetchAllFromScroll(mockResponse as any, stubCallWithRequest); expect(stubCallWithRequest).toHaveBeenCalledTimes(0); }); }); @@ -53,12 +52,12 @@ describe('fetch_all_from_scroll', () => { }; it('should return the hits from the response', async () => { - const hits = await fetchAllFromScroll(mockResponse, stubCallWithRequest); + const hits = await fetchAllFromScroll(mockResponse as any, stubCallWithRequest); expect(hits).toEqual(['foo', 'bar', 'newhit']); }); it('should call callWithRequest', async () => { - await fetchAllFromScroll(mockResponse, stubCallWithRequest); + await fetchAllFromScroll(mockResponse as any, stubCallWithRequest); expect(stubCallWithRequest).toHaveBeenCalledTimes(2); const firstCallWithRequestCallArgs = stubCallWithRequest.mock.calls[0]; diff --git a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts index 779b160db7ee5..57411d7900719 100755 --- a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts +++ b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts @@ -4,29 +4,31 @@ * you may not use this file except in compliance with the Elastic License. */ import { APICaller } from 'src/core/server'; -import { get } from 'lodash'; +import { SearchResponse } from 'elasticsearch'; + import { ES_SCROLL_SETTINGS } from '../../../common/constants'; +type Hits = SearchResponse['hits']['hits']; -export function fetchAllFromScroll( - response: Record, +export async function fetchAllFromScroll( + response: SearchResponse, callWithRequest: APICaller, - hits = [] -): Record { - const newHits = get(response, 'hits.hits', []); - const scrollId = get(response, '_scroll_id'); + hits: Hits = [] +): Promise { + const newHits = response.hits.hits; + const scrollId = response._scroll_id; if (newHits.length > 0) { hits.push(...newHits); - return callWithRequest('scroll', { + const innerResponse = await callWithRequest('scroll', { body: { scroll: ES_SCROLL_SETTINGS.KEEPALIVE, scroll_id: scrollId, }, - }).then(innerResponse => { - return fetchAllFromScroll(innerResponse, callWithRequest, hits); }); + + return await fetchAllFromScroll(innerResponse, callWithRequest, hits); } - return Promise.resolve(hits); + return hits; } From 877fa0fda0eb2de896df30dc676e98457fbd47b5 Mon Sep 17 00:00:00 2001 From: restrry Date: Thu, 9 Apr 2020 17:07:20 +0200 Subject: [PATCH 05/13] move route declaration to NP --- .../call_with_request_factory.js | 18 ----- .../__tests__/wrap_custom_error.js | 21 ------ .../error_wrappers/__tests__/wrap_es_error.js | 42 ----------- .../__tests__/wrap_unknown_error.js | 19 ----- .../lib/error_wrappers/wrap_custom_error.js | 18 ----- .../lib/error_wrappers/wrap_es_error.js | 27 ------- .../lib/error_wrappers/wrap_unknown_error.js | 17 ----- .../__tests__/license_pre_routing_factory.js | 69 ------------------ .../license_pre_routing_factory.js | 27 ------- .../api/cluster/register_cluster_routes.js | 11 --- .../routes/api/cluster/register_load_route.js | 40 ---------- .../server/routes/api/pipeline/index.js | 7 -- .../api/pipeline/register_delete_route.js | 38 ---------- .../api/pipeline/register_load_route.js | 48 ------------ .../api/pipeline/register_pipeline_routes.js | 15 ---- .../api/pipeline/register_save_route.js | 49 ------------- .../server/routes/api/pipelines/index.js | 7 -- .../api/pipelines/register_delete_route.js | 51 ------------- .../api/pipelines/register_list_route.js | 57 --------------- .../pipelines/register_pipelines_routes.js | 13 ---- .../server/routes/api/upgrade/index.js | 7 -- .../api/upgrade/register_execute_route.js | 56 -------------- .../api/upgrade/register_upgrade_routes.js | 11 --- .../logstash/server/routes/cluster/index.ts} | 3 +- .../logstash/server/routes/cluster/load.ts | 37 ++++++++++ .../plugins/logstash/server/routes/index.ts | 29 +++++++- .../logstash/server/routes/pipeline/delete.ts | 38 ++++++++++ .../logstash/server/routes/pipeline/index.ts} | 7 +- .../logstash/server/routes/pipeline/load.ts | 46 ++++++++++++ .../logstash/server/routes/pipeline/save.ts | 73 +++++++++++++++++++ .../server/routes/pipelines/delete.ts | 54 ++++++++++++++ .../server/routes/pipelines/index.ts} | 4 +- .../logstash/server/routes/pipelines/list.ts | 63 ++++++++++++++++ .../logstash/server/routes/upgrade/execute.ts | 46 ++++++++++++ .../logstash/server/routes/upgrade/index.ts} | 2 +- 35 files changed, 391 insertions(+), 679 deletions(-) delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/call_with_request_factory.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_custom_error.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_es_error.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_unknown_error.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_custom_error.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_es_error.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_unknown_error.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js delete mode 100755 x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_cluster_routes.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_load_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipeline/index.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_delete_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_load_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_pipeline_routes.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_save_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipelines/index.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_delete_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_list_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_pipelines_routes.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/upgrade/index.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_execute_route.js delete mode 100755 x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_upgrade_routes.js rename x-pack/{legacy/plugins/logstash/server/lib/license_pre_routing_factory/index.js => plugins/logstash/server/routes/cluster/index.ts} (76%) mode change 100755 => 100644 create mode 100644 x-pack/plugins/logstash/server/routes/cluster/load.ts create mode 100644 x-pack/plugins/logstash/server/routes/pipeline/delete.ts rename x-pack/{legacy/plugins/logstash/server/lib/error_wrappers/index.js => plugins/logstash/server/routes/pipeline/index.ts} (60%) mode change 100755 => 100644 create mode 100644 x-pack/plugins/logstash/server/routes/pipeline/load.ts create mode 100644 x-pack/plugins/logstash/server/routes/pipeline/save.ts create mode 100644 x-pack/plugins/logstash/server/routes/pipelines/delete.ts rename x-pack/{legacy/plugins/logstash/server/routes/api/cluster/index.js => plugins/logstash/server/routes/pipelines/index.ts} (68%) mode change 100755 => 100644 create mode 100644 x-pack/plugins/logstash/server/routes/pipelines/list.ts create mode 100644 x-pack/plugins/logstash/server/routes/upgrade/execute.ts rename x-pack/{legacy/plugins/logstash/server/lib/call_with_request_factory/index.js => plugins/logstash/server/routes/upgrade/index.ts} (77%) mode change 100755 => 100644 diff --git a/x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/call_with_request_factory.js b/x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/call_with_request_factory.js deleted file mode 100755 index 8dc09d394e973..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/call_with_request_factory.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 { once } from 'lodash'; - -const callWithRequest = once(server => { - const cluster = server.plugins.elasticsearch.createCluster('logstash'); - return cluster.callWithRequest; -}); - -export const callWithRequestFactory = (server, request) => { - return (...args) => { - return callWithRequest(server)(request, ...args); - }; -}; diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_custom_error.js deleted file mode 100755 index f9c102be7a1ff..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_custom_error.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 { wrapCustomError } from '../wrap_custom_error'; - -describe('wrap_custom_error', () => { - describe('#wrapCustomError', () => { - it('should return a Boom object', () => { - const originalError = new Error('I am an error'); - const statusCode = 404; - const wrappedError = wrapCustomError(originalError, statusCode); - - expect(wrappedError.isBoom).to.be(true); - expect(wrappedError.output.statusCode).to.equal(statusCode); - }); - }); -}); diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_es_error.js deleted file mode 100755 index cab25cd0b1b10..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_es_error.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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 { wrapEsError } from '../wrap_es_error'; - -describe('wrap_es_error', () => { - describe('#wrapEsError', () => { - let originalError; - beforeEach(() => { - originalError = new Error('I am an error'); - originalError.statusCode = 404; - }); - - it('should return a Boom object', () => { - const wrappedError = wrapEsError(originalError); - - expect(wrappedError.isBoom).to.be(true); - }); - - it('should return the correct Boom object', () => { - const wrappedError = wrapEsError(originalError); - - expect(wrappedError.output.statusCode).to.be(originalError.statusCode); - expect(wrappedError.output.payload.message).to.be(originalError.message); - }); - - it('should return invalid permissions message for 403 errors', () => { - const securityError = new Error('I am an error'); - securityError.statusCode = 403; - const wrappedError = wrapEsError(securityError); - - expect(wrappedError.isBoom).to.be(true); - expect(wrappedError.message).to.be( - 'Insufficient user permissions for managing Logstash pipelines' - ); - }); - }); -}); diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_unknown_error.js deleted file mode 100755 index 85e0b2b3033ad..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/__tests__/wrap_unknown_error.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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 { wrapUnknownError } from '../wrap_unknown_error'; - -describe('wrap_unknown_error', () => { - describe('#wrapUnknownError', () => { - it('should return a Boom object', () => { - const originalError = new Error('I am an error'); - const wrappedError = wrapUnknownError(originalError); - - expect(wrappedError.isBoom).to.be(true); - }); - }); -}); diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_custom_error.js b/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_custom_error.js deleted file mode 100755 index 3295113d38ee5..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_custom_error.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 Boom from 'boom'; - -/** - * Wraps a custom error into a Boom error response and returns it - * - * @param err Object error - * @param statusCode Error status code - * @return Object Boom error response - */ -export function wrapCustomError(err, statusCode) { - return Boom.boomify(err, { statusCode }); -} diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_es_error.js b/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_es_error.js deleted file mode 100755 index 41819179bde55..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_es_error.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 Boom from 'boom'; -import { i18n } from '@kbn/i18n'; - -/** - * Wraps ES errors into a Boom error response and returns it - * This also handles the permissions issue gracefully - * - * @param err Object ES error - * @return Object Boom error response - */ -export function wrapEsError(err) { - const statusCode = err.statusCode; - if (statusCode === 403) { - return Boom.forbidden( - i18n.translate('xpack.logstash.insufficientUserPermissionsDescription', { - defaultMessage: 'Insufficient user permissions for managing Logstash pipelines', - }) - ); - } - return Boom.boomify(err, { statusCode: err.statusCode }); -} diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_unknown_error.js b/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_unknown_error.js deleted file mode 100755 index ffd915c513362..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/wrap_unknown_error.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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 Boom from 'boom'; - -/** - * Wraps an unknown error into a Boom error response and returns it - * - * @param err Object Unknown error - * @return Object Boom error response - */ -export function wrapUnknownError(err) { - return Boom.boomify(err); -} diff --git a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js deleted file mode 100755 index 1dc1df922acf7..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 { licensePreRoutingFactory } from '../license_pre_routing_factory'; - -describe('license_pre_routing_factory', () => { - describe('#logstashFeaturePreRoutingFactory', () => { - let mockServer; - let mockLicenseCheckResults; - - beforeEach(() => { - mockServer = { - plugins: { - xpack_main: { - info: { - feature: () => ({ - getLicenseCheckResults: () => mockLicenseCheckResults, - }), - }, - }, - }, - }; - }); - - it('only instantiates one instance per server', () => { - const firstInstance = licensePreRoutingFactory(mockServer); - const secondInstance = licensePreRoutingFactory(mockServer); - - expect(firstInstance).to.be(secondInstance); - }); - - describe('isAvailable is false', () => { - beforeEach(() => { - mockLicenseCheckResults = { - isAvailable: false, - }; - }); - - it('replies with 403', () => { - const licensePreRouting = licensePreRoutingFactory(mockServer); - const stubRequest = {}; - expect(() => licensePreRouting(stubRequest)).to.throwException(response => { - expect(response).to.be.an(Error); - expect(response.isBoom).to.be(true); - expect(response.output.statusCode).to.be(403); - }); - }); - }); - - describe('isAvailable is true', () => { - beforeEach(() => { - mockLicenseCheckResults = { - isAvailable: true, - }; - }); - - it('replies with nothing', () => { - const licensePreRouting = licensePreRoutingFactory(mockServer); - const stubRequest = {}; - const response = licensePreRouting(stubRequest); - expect(response).to.be(null); - }); - }); - }); -}); diff --git a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js b/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js deleted file mode 100755 index 461fb0846eca8..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/license_pre_routing_factory.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 { once } from 'lodash'; -import { wrapCustomError } from '../error_wrappers'; -import { PLUGIN } from '../../../../../../plugins/logstash/common/constants'; - -export const licensePreRoutingFactory = once(server => { - const xpackMainPlugin = server.plugins.xpack_main; - - // License checking and enable/disable logic - function licensePreRouting() { - const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults(); - if (!licenseCheckResults.isAvailable) { - const error = new Error(licenseCheckResults.message); - const statusCode = 403; - throw wrapCustomError(error, statusCode); - } - - return null; - } - - return licensePreRouting; -}); diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_cluster_routes.js b/x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_cluster_routes.js deleted file mode 100755 index 86e18b02ddce2..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_cluster_routes.js +++ /dev/null @@ -1,11 +0,0 @@ -/* - * 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 { registerLoadRoute } from './register_load_route'; - -export function registerLogstashClusterRoutes(server) { - registerLoadRoute(server); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_load_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_load_route.js deleted file mode 100755 index 663b60cc8c1d1..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/cluster/register_load_route.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 Boom from 'boom'; -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { Cluster } from '../../../models/cluster'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function fetchCluster(callWithRequest) { - return callWithRequest('info'); -} - -export function registerLoadRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/cluster', - method: 'GET', - handler: (request, h) => { - const callWithRequest = callWithRequestFactory(server, request); - - return fetchCluster(callWithRequest) - .then(responseFromES => ({ - cluster: Cluster.fromUpstreamJSON(responseFromES).downstreamJSON, - })) - .catch(e => { - if (e.status === 403) { - return h.response(); - } - throw Boom.internal(e); - }); - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/index.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/index.js deleted file mode 100755 index 643a405ced919..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * 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. - */ - -export { registerLogstashPipelineRoutes } from './register_pipeline_routes'; diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_delete_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_delete_route.js deleted file mode 100755 index 42c77a4444249..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_delete_route.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { wrapEsError } from '../../../lib/error_wrappers'; -import { INDEX_NAMES } from '../../../../../../../plugins/logstash/common/constants'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function deletePipeline(callWithRequest, pipelineId) { - return callWithRequest('delete', { - index: INDEX_NAMES.PIPELINES, - id: pipelineId, - refresh: 'wait_for', - }); -} - -export function registerDeleteRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/pipeline/{id}', - method: 'DELETE', - handler: (request, h) => { - const callWithRequest = callWithRequestFactory(server, request); - const pipelineId = request.params.id; - - return deletePipeline(callWithRequest, pipelineId) - .then(() => h.response().code(204)) - .catch(e => wrapEsError(e)); - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_load_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_load_route.js deleted file mode 100755 index 6a385614ed99c..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_load_route.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 Boom from 'boom'; -import { INDEX_NAMES } from '../../../../../../../plugins/logstash/common/constants'; -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { Pipeline } from '../../../../../../../plugins/logstash/server/models/pipeline'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function fetchPipeline(callWithRequest, pipelineId) { - return callWithRequest('get', { - index: INDEX_NAMES.PIPELINES, - id: pipelineId, - _source: ['description', 'username', 'pipeline', 'pipeline_settings'], - ignore: [404], - }); -} - -export function registerLoadRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/pipeline/{id}', - method: 'GET', - handler: request => { - const callWithRequest = callWithRequestFactory(server, request); - const pipelineId = request.params.id; - - return fetchPipeline(callWithRequest, pipelineId) - .then(pipelineResponseFromES => { - if (!pipelineResponseFromES.found) { - throw Boom.notFound(); - } - - const pipeline = Pipeline.fromUpstreamJSON(pipelineResponseFromES); - return pipeline.downstreamJSON; - }) - .catch(e => Boom.boomify(e)); - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_pipeline_routes.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_pipeline_routes.js deleted file mode 100755 index 9966cd2ca2139..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_pipeline_routes.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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 { registerLoadRoute } from './register_load_route'; -import { registerDeleteRoute } from './register_delete_route'; -import { registerSaveRoute } from './register_save_route'; - -export function registerLogstashPipelineRoutes(server) { - registerLoadRoute(server); - registerDeleteRoute(server); - registerSaveRoute(server); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_save_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_save_route.js deleted file mode 100755 index 87b56bd84584c..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipeline/register_save_route.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 { get } from 'lodash'; -import { wrapEsError } from '../../../lib/error_wrappers'; -import { INDEX_NAMES } from '../../../../../../../plugins/logstash/common/constants'; -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { Pipeline } from '../../../../../../../plugins/logstash/server/models/pipeline'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function savePipeline(callWithRequest, pipelineId, pipelineBody) { - return callWithRequest('index', { - index: INDEX_NAMES.PIPELINES, - id: pipelineId, - body: pipelineBody, - refresh: 'wait_for', - }); -} - -export function registerSaveRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/pipeline/{id}', - method: 'PUT', - handler: async (request, h) => { - let username; - if (server.plugins.security) { - const user = await server.plugins.security.getUser(request); - username = get(user, 'username'); - } - - const callWithRequest = callWithRequestFactory(server, request); - const pipelineId = request.params.id; - - const pipeline = Pipeline.fromDownstreamJSON(request.payload, pipelineId, username); - return savePipeline(callWithRequest, pipeline.id, pipeline.upstreamJSON) - .then(() => h.response().code(204)) - .catch(e => wrapEsError(e)); - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/index.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/index.js deleted file mode 100755 index db275b5a3ea79..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * 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. - */ - -export { registerLogstashPipelinesRoutes } from './register_pipelines_routes'; diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_delete_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_delete_route.js deleted file mode 100755 index 637e8ea8d5c38..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_delete_route.js +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { wrapUnknownError } from '../../../lib/error_wrappers'; -import { INDEX_NAMES } from '../../../../../../../plugins/logstash/common/constants'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function deletePipelines(callWithRequest, pipelineIds) { - const deletePromises = pipelineIds.map(pipelineId => { - return callWithRequest('delete', { - index: INDEX_NAMES.PIPELINES, - id: pipelineId, - refresh: 'wait_for', - }) - .then(success => ({ success })) - .catch(error => ({ error })); - }); - - return Promise.all(deletePromises).then(results => { - const successes = results.filter(result => Boolean(result.success)); - const errors = results.filter(result => Boolean(result.error)); - - return { - numSuccesses: successes.length, - numErrors: errors.length, - }; - }); -} - -export function registerDeleteRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/pipelines/delete', - method: 'POST', - handler: request => { - const callWithRequest = callWithRequestFactory(server, request); - - return deletePipelines(callWithRequest, request.payload.pipelineIds) - .then(results => ({ results })) - .catch(err => wrapUnknownError(err)); - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_list_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_list_route.js deleted file mode 100755 index 16446e2204db8..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_list_route.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 { wrapEsError } from '../../../lib/error_wrappers'; -import { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { fetchAllFromScroll } from '../../../../../../../plugins/logstash/server/lib/fetch_all_from_scroll'; -import { - INDEX_NAMES, - ES_SCROLL_SETTINGS, -} from '../../../../../../../plugins/logstash/common/constants'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import { PipelineListItem } from '../../../../../../../plugins/logstash/server/models/pipeline_list_item'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function fetchPipelines(callWithRequest) { - const params = { - index: INDEX_NAMES.PIPELINES, - scroll: ES_SCROLL_SETTINGS.KEEPALIVE, - body: { - size: ES_SCROLL_SETTINGS.PAGE_SIZE, - }, - ignore: [404], - }; - - return callWithRequest('search', params).then(response => - fetchAllFromScroll(response, callWithRequest) - ); -} - -export function registerListRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/pipelines', - method: 'GET', - handler: request => { - const callWithRequest = callWithRequestFactory(server, request); - - return fetchPipelines(callWithRequest) - .then((pipelinesHits = []) => { - const pipelines = pipelinesHits.map(pipeline => { - return PipelineListItem.fromUpstreamJSON(pipeline).downstreamJSON; - }); - - return { pipelines }; - }) - .catch(e => wrapEsError(e)); - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_pipelines_routes.js b/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_pipelines_routes.js deleted file mode 100755 index 6d25f3acb9bf9..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/pipelines/register_pipelines_routes.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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 { registerListRoute } from './register_list_route'; -import { registerDeleteRoute } from './register_delete_route'; - -export function registerLogstashPipelinesRoutes(server) { - registerListRoute(server); - registerDeleteRoute(server); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/index.js b/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/index.js deleted file mode 100755 index d616349dd6566..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/index.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - * 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. - */ - -export { registerLogstashUpgradeRoutes } from './register_upgrade_routes'; diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_execute_route.js b/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_execute_route.js deleted file mode 100755 index 62e60a99d2eea..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_execute_route.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 { callWithRequestFactory } from '../../../lib/call_with_request_factory'; -import { wrapUnknownError } from '../../../lib/error_wrappers'; -import { INDEX_NAMES } from '../../../../../../../plugins/logstash/common/constants'; -import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory'; - -function doesIndexExist(callWithRequest) { - return callWithRequest('indices.exists', { - index: INDEX_NAMES.PIPELINES, - }); -} - -async function executeUpgrade(callWithRequest) { - // If index doesn't exist yet, there is no mapping to upgrade - if (!(await doesIndexExist(callWithRequest))) { - return; - } - - return callWithRequest('indices.putMapping', { - index: INDEX_NAMES.PIPELINES, - body: { - properties: { - pipeline_settings: { - dynamic: false, - type: 'object', - }, - }, - }, - }); -} - -export function registerExecuteRoute(server) { - const licensePreRouting = licensePreRoutingFactory(server); - - server.route({ - path: '/api/logstash/upgrade', - method: 'POST', - handler: async request => { - const callWithRequest = callWithRequestFactory(server, request); - try { - await executeUpgrade(callWithRequest); - return { is_upgraded: true }; - } catch (err) { - throw wrapUnknownError(err); - } - }, - config: { - pre: [licensePreRouting], - }, - }); -} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_upgrade_routes.js b/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_upgrade_routes.js deleted file mode 100755 index a198f82613e37..0000000000000 --- a/x-pack/legacy/plugins/logstash/server/routes/api/upgrade/register_upgrade_routes.js +++ /dev/null @@ -1,11 +0,0 @@ -/* - * 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 { registerExecuteRoute } from './register_execute_route'; - -export function registerLogstashUpgradeRoutes(server) { - registerExecuteRoute(server); -} diff --git a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/index.js b/x-pack/plugins/logstash/server/routes/cluster/index.ts old mode 100755 new mode 100644 similarity index 76% rename from x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/index.js rename to x-pack/plugins/logstash/server/routes/cluster/index.ts index 0743e443955f4..c43c409cf5a17 --- a/x-pack/legacy/plugins/logstash/server/lib/license_pre_routing_factory/index.js +++ b/x-pack/plugins/logstash/server/routes/cluster/index.ts @@ -3,5 +3,4 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -export { licensePreRoutingFactory } from './license_pre_routing_factory'; +export { registerClusterLoadRoute } from './load'; diff --git a/x-pack/plugins/logstash/server/routes/cluster/load.ts b/x-pack/plugins/logstash/server/routes/cluster/load.ts new file mode 100644 index 0000000000000..19f207bb5ea61 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/cluster/load.ts @@ -0,0 +1,37 @@ +/* + * 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 { ICustomClusterClient, IRouter } from 'src/core/server'; +import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; +import { Cluster } from '../../models/cluster'; +import { checkLicense } from '../../lib/check_license'; + +export function registerClusterLoadRoute(router: IRouter, esClient: ICustomClusterClient) { + router.get( + { + path: '/api/logstash/cluster', + validate: false, + }, + licenseCheckerRouteHandlerWrapper( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + try { + const client = esClient.asScoped(request); + const info = await client.callAsCurrentUser('info'); + return response.ok({ + body: { + cluster: Cluster.fromUpstreamJSON(info).downstreamJSON, + }, + }); + } catch (err) { + if (err.status === 403) { + return response.ok(); + } + return response.internalError(); + } + }) + ) + ); +} diff --git a/x-pack/plugins/logstash/server/routes/index.ts b/x-pack/plugins/logstash/server/routes/index.ts index 6dac28828a1ea..771ef83e49b21 100644 --- a/x-pack/plugins/logstash/server/routes/index.ts +++ b/x-pack/plugins/logstash/server/routes/index.ts @@ -3,5 +3,30 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { IRouter } from 'src/core/server'; -export function registerRoutes(router: IRouter) {} +import { IRouter, ICustomClusterClient } from 'src/core/server'; +import { SecurityPluginSetup } from '../../../security/server'; +import { registerClusterLoadRoute } from './cluster'; +import { + registerPipelineDeleteRoute, + registerPipelineLoadRoute, + registerPipelineSaveRoute, +} from './pipeline'; +import { registerPipelinesListRoute, registerPipelinesDeleteRoute } from './pipelines'; +import { registerUpgradeRoute } from './upgrade'; + +export function registerRoutes( + router: IRouter, + esClient: ICustomClusterClient, + security?: SecurityPluginSetup +) { + registerClusterLoadRoute(router, esClient); + + registerPipelineDeleteRoute(router, esClient); + registerPipelineLoadRoute(router, esClient); + registerPipelineSaveRoute(router, esClient, security); + + registerPipelinesListRoute(router, esClient); + registerPipelinesDeleteRoute(router, esClient); + + registerUpgradeRoute(router, esClient); +} diff --git a/x-pack/plugins/logstash/server/routes/pipeline/delete.ts b/x-pack/plugins/logstash/server/routes/pipeline/delete.ts new file mode 100644 index 0000000000000..73c1029dd3273 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/pipeline/delete.ts @@ -0,0 +1,38 @@ +/* + * 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 { schema } from '@kbn/config-schema'; +import { ICustomClusterClient, IRouter } from 'src/core/server'; +import { INDEX_NAMES } from '../../../common/constants'; +import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; + +import { checkLicense } from '../../lib/check_license'; + +export function registerPipelineDeleteRoute(router: IRouter, esClient: ICustomClusterClient) { + router.delete( + { + path: '/api/logstash/pipeline/{id}', + validate: { + params: schema.object({ + id: schema.string(), + }), + }, + }, + licenseCheckerRouteHandlerWrapper( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + const client = esClient.asScoped(request); + + await client.callAsCurrentUser('delete', { + index: INDEX_NAMES.PIPELINES, + id: request.params.id, + refresh: 'wait_for', + }); + + return response.noContent(); + }) + ) + ); +} diff --git a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/index.js b/x-pack/plugins/logstash/server/routes/pipeline/index.ts old mode 100755 new mode 100644 similarity index 60% rename from x-pack/legacy/plugins/logstash/server/lib/error_wrappers/index.js rename to x-pack/plugins/logstash/server/routes/pipeline/index.ts index f275f15637091..e7db6e18ddaf3 --- a/x-pack/legacy/plugins/logstash/server/lib/error_wrappers/index.js +++ b/x-pack/plugins/logstash/server/routes/pipeline/index.ts @@ -3,7 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -export { wrapCustomError } from './wrap_custom_error'; -export { wrapEsError } from './wrap_es_error'; -export { wrapUnknownError } from './wrap_unknown_error'; +export { registerPipelineDeleteRoute } from './delete'; +export { registerPipelineLoadRoute } from './load'; +export { registerPipelineSaveRoute } from './save'; diff --git a/x-pack/plugins/logstash/server/routes/pipeline/load.ts b/x-pack/plugins/logstash/server/routes/pipeline/load.ts new file mode 100644 index 0000000000000..cfc1a92864213 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/pipeline/load.ts @@ -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 { schema } from '@kbn/config-schema'; +import { ICustomClusterClient, IRouter } from 'src/core/server'; + +import { INDEX_NAMES } from '../../../common/constants'; +import { Pipeline } from '../../models/pipeline'; +import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; +import { checkLicense } from '../../lib/check_license'; + +export function registerPipelineLoadRoute(router: IRouter, esClient: ICustomClusterClient) { + router.get( + { + path: '/api/logstash/pipeline/{id}', + validate: { + params: schema.object({ + id: schema.string(), + }), + }, + }, + licenseCheckerRouteHandlerWrapper( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + const client = esClient.asScoped(request); + + const result = await client.callAsCurrentUser('get', { + index: INDEX_NAMES.PIPELINES, + id: request.params.id, + _source: ['description', 'username', 'pipeline', 'pipeline_settings'], + ignore: [404], + }); + + if (!result.found) { + return response.notFound(); + } + + return response.ok({ + body: Pipeline.fromUpstreamJSON(result).downstreamJSON, + }); + }) + ) + ); +} diff --git a/x-pack/plugins/logstash/server/routes/pipeline/save.ts b/x-pack/plugins/logstash/server/routes/pipeline/save.ts new file mode 100644 index 0000000000000..23a1a8237a806 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/pipeline/save.ts @@ -0,0 +1,73 @@ +/* + * 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 { schema } from '@kbn/config-schema'; +import { i18n } from '@kbn/i18n'; +import { ICustomClusterClient, IRouter } from 'src/core/server'; + +import { INDEX_NAMES } from '../../../common/constants'; +import { Pipeline } from '../../models/pipeline'; +import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; +import { SecurityPluginSetup } from '../../../../security/server'; +import { checkLicense } from '../../lib/check_license'; + +export function registerPipelineSaveRoute( + router: IRouter, + esClient: ICustomClusterClient, + security?: SecurityPluginSetup +) { + router.put( + { + path: '/api/logstash/pipeline/{id}', + validate: { + params: schema.object({ + id: schema.string(), + }), + body: schema.object({ + id: schema.string(), + description: schema.string(), + pipeline: schema.string(), + username: schema.string(), + settings: schema.maybe(schema.object({}, { unknowns: 'ignore' })), + }), + }, + }, + licenseCheckerRouteHandlerWrapper( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + try { + let username: string | undefined; + if (security) { + const user = await security.authc.getCurrentUser(request); + username = user?.username; + } + + const client = esClient.asScoped(request); + const pipeline = Pipeline.fromDownstreamJSON(request.body, request.params.id, username); + + await client.callAsCurrentUser('index', { + index: INDEX_NAMES.PIPELINES, + id: pipeline.id, + body: pipeline.upstreamJSON, + refresh: 'wait_for', + }); + + return response.noContent(); + } catch (err) { + const statusCode = err.statusCode; + // handles the permissions issue of Elasticsearch + if (statusCode === 403) { + return response.forbidden({ + body: i18n.translate('xpack.logstash.insufficientUserPermissionsDescription', { + defaultMessage: 'Insufficient user permissions for managing Logstash pipelines', + }), + }); + } + throw err; + } + }) + ) + ); +} diff --git a/x-pack/plugins/logstash/server/routes/pipelines/delete.ts b/x-pack/plugins/logstash/server/routes/pipelines/delete.ts new file mode 100644 index 0000000000000..5e2e6ef3d77c2 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/pipelines/delete.ts @@ -0,0 +1,54 @@ +/* + * 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 { schema } from '@kbn/config-schema'; +import { APICaller, ICustomClusterClient, IRouter } from 'src/core/server'; +import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; + +import { INDEX_NAMES } from '../../../common/constants'; +import { checkLicense } from '../../lib/check_license'; + +async function deletePipelines(callWithRequest: APICaller, pipelineIds: string[]) { + const deletePromises = pipelineIds.map(pipelineId => { + return callWithRequest('delete', { + index: INDEX_NAMES.PIPELINES, + id: pipelineId, + refresh: 'wait_for', + }) + .then(success => ({ success })) + .catch(error => ({ error })); + }); + + const results = await Promise.all(deletePromises); + const successes = results.filter(result => Reflect.has(result, 'success')); + const errors = results.filter(result => Reflect.has(result, 'error')); + + return { + numSuccesses: successes.length, + numErrors: errors.length, + }; +} + +export function registerPipelinesDeleteRoute(router: IRouter, esClient: ICustomClusterClient) { + router.post( + { + path: '/api/logstash/pipelines/delete', + validate: { + body: schema.object({ + pipelineIds: schema.arrayOf(schema.string()), + }), + }, + }, + licenseCheckerRouteHandlerWrapper( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + const client = esClient.asScoped(request); + const results = await deletePipelines(client.callAsCurrentUser, request.body.pipelineIds); + + return response.ok({ body: { results } }); + }) + ) + ); +} diff --git a/x-pack/legacy/plugins/logstash/server/routes/api/cluster/index.js b/x-pack/plugins/logstash/server/routes/pipelines/index.ts old mode 100755 new mode 100644 similarity index 68% rename from x-pack/legacy/plugins/logstash/server/routes/api/cluster/index.js rename to x-pack/plugins/logstash/server/routes/pipelines/index.ts index b129d8524b573..36681502cfc70 --- a/x-pack/legacy/plugins/logstash/server/routes/api/cluster/index.js +++ b/x-pack/plugins/logstash/server/routes/pipelines/index.ts @@ -3,5 +3,5 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - -export { registerLogstashClusterRoutes } from './register_cluster_routes'; +export { registerPipelinesListRoute } from './list'; +export { registerPipelinesDeleteRoute } from './delete'; diff --git a/x-pack/plugins/logstash/server/routes/pipelines/list.ts b/x-pack/plugins/logstash/server/routes/pipelines/list.ts new file mode 100644 index 0000000000000..eaa4a49b93aeb --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/pipelines/list.ts @@ -0,0 +1,63 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import { SearchResponse } from 'elasticsearch'; +import { APICaller, ICustomClusterClient, IRouter } from 'src/core/server'; +import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; + +import { INDEX_NAMES, ES_SCROLL_SETTINGS } from '../../../common/constants'; +import { PipelineListItem } from '../../models/pipeline_list_item'; +import { fetchAllFromScroll } from '../../lib/fetch_all_from_scroll'; +import { checkLicense } from '../../lib/check_license'; + +async function fetchPipelines(callWithRequest: APICaller) { + const params = { + index: INDEX_NAMES.PIPELINES, + scroll: ES_SCROLL_SETTINGS.KEEPALIVE, + body: { + size: ES_SCROLL_SETTINGS.PAGE_SIZE, + }, + ignore: [404], + }; + + const response = await callWithRequest>('search', params); + return fetchAllFromScroll(response, callWithRequest); +} + +export function registerPipelinesListRoute(router: IRouter, esClient: ICustomClusterClient) { + router.get( + { + path: '/api/logstash/pipelines', + validate: false, + }, + licenseCheckerRouteHandlerWrapper( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + try { + const client = esClient.asScoped(request); + const pipelinesHits = await fetchPipelines(client.callAsCurrentUser); + + const pipelines = pipelinesHits.map(pipeline => { + return PipelineListItem.fromUpstreamJSON(pipeline).downstreamJSON; + }); + + return response.ok({ body: { pipelines } }); + } catch (err) { + const statusCode = err.statusCode; + // handles the permissions issue of Elasticsearch + if (statusCode === 403) { + return response.forbidden({ + body: i18n.translate('xpack.logstash.insufficientUserPermissionsDescription', { + defaultMessage: 'Insufficient user permissions for managing Logstash pipelines', + }), + }); + } + throw err; + } + }) + ) + ); +} diff --git a/x-pack/plugins/logstash/server/routes/upgrade/execute.ts b/x-pack/plugins/logstash/server/routes/upgrade/execute.ts new file mode 100644 index 0000000000000..e844830379f88 --- /dev/null +++ b/x-pack/plugins/logstash/server/routes/upgrade/execute.ts @@ -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 { ICustomClusterClient, IRouter } from 'src/core/server'; +import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; + +import { INDEX_NAMES } from '../../../common/constants'; +import { checkLicense } from '../../lib/check_license'; + +export function registerUpgradeRoute(router: IRouter, esClient: ICustomClusterClient) { + router.post( + { + path: '/api/logstash/upgrade', + validate: false, + }, + licenseCheckerRouteHandlerWrapper( + checkLicense, + router.handleLegacyErrors(async (context, request, response) => { + const client = esClient.asScoped(request); + + const doesIndexExist = await client.callAsCurrentUser('indices.exists', { + index: INDEX_NAMES.PIPELINES, + }); + + // If index doesn't exist yet, there is no mapping to upgrade + if (doesIndexExist) { + await client.callAsCurrentUser('indices.putMapping', { + index: INDEX_NAMES.PIPELINES, + body: { + properties: { + pipeline_settings: { + dynamic: false, + type: 'object', + }, + }, + }, + }); + } + + return response.ok({ body: { is_upgraded: true } }); + }) + ) + ); +} diff --git a/x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/index.js b/x-pack/plugins/logstash/server/routes/upgrade/index.ts old mode 100755 new mode 100644 similarity index 77% rename from x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/index.js rename to x-pack/plugins/logstash/server/routes/upgrade/index.ts index 787814d87dff9..b2e65aece4dc6 --- a/x-pack/legacy/plugins/logstash/server/lib/call_with_request_factory/index.js +++ b/x-pack/plugins/logstash/server/routes/upgrade/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { callWithRequestFactory } from './call_with_request_factory'; +export { registerUpgradeRoute } from './execute'; From f3385eed76391c473bd1c066696f3c5586686c81 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Thu, 9 Apr 2020 17:08:45 +0200 Subject: [PATCH 06/13] add licence checker wrapper --- .../licensing/common/licensing.mock.ts | 1 + x-pack/plugins/licensing/server/index.ts | 4 ++ .../license_checker_route_handler_wrapper.ts | 40 +++++++++++++ ...sing_checker_route_handler_wrapper.test.ts | 59 +++++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 x-pack/plugins/licensing/server/license_checker_route_handler_wrapper.ts create mode 100644 x-pack/plugins/licensing/server/licensing_checker_route_handler_wrapper.test.ts diff --git a/x-pack/plugins/licensing/common/licensing.mock.ts b/x-pack/plugins/licensing/common/licensing.mock.ts index bf8b85e3e981b..4a6b27255587a 100644 --- a/x-pack/plugins/licensing/common/licensing.mock.ts +++ b/x-pack/plugins/licensing/common/licensing.mock.ts @@ -53,6 +53,7 @@ const createLicenseMock = () => { }; mock.check.mockReturnValue({ state: 'valid' }); mock.hasAtLeast.mockReturnValue(true); + mock.getFeature.mockReturnValue({ isAvailable: true, isEnabled: true }); return mock; }; export const licenseMock = { diff --git a/x-pack/plugins/licensing/server/index.ts b/x-pack/plugins/licensing/server/index.ts index 0e14ead7c6c57..1f95459513814 100644 --- a/x-pack/plugins/licensing/server/index.ts +++ b/x-pack/plugins/licensing/server/index.ts @@ -12,3 +12,7 @@ export const plugin = (context: PluginInitializerContext) => new LicensingPlugin export * from '../common/types'; export * from './types'; export { config } from './licensing_config'; +export { + CheckLicense, + licenseCheckerRouteHandlerWrapper, +} from './license_checker_route_handler_wrapper'; diff --git a/x-pack/plugins/licensing/server/license_checker_route_handler_wrapper.ts b/x-pack/plugins/licensing/server/license_checker_route_handler_wrapper.ts new file mode 100644 index 0000000000000..7f07a054c41b7 --- /dev/null +++ b/x-pack/plugins/licensing/server/license_checker_route_handler_wrapper.ts @@ -0,0 +1,40 @@ +/* + * 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 { + RequestHandler, + RequestHandlerContext, + KibanaRequest, + RouteMethod, + KibanaResponseFactory, +} from 'src/core/server'; + +import { ILicense } from '../common/types'; + +export type CheckLicense = ( + license: ILicense +) => { valid: false; message: string } | { valid: true; message: null }; + +export function licenseCheckerRouteHandlerWrapper( + checkLicense: CheckLicense, + handler: RequestHandler +): RequestHandler { + return async ( + context: RequestHandlerContext, + request: KibanaRequest, + response: KibanaResponseFactory + ) => { + const licenseCheckResult = checkLicense(context.licensing.license); + + if (licenseCheckResult.valid) { + return handler(context, request, response); + } else { + return response.forbidden({ + body: licenseCheckResult.message, + }); + } + }; +} diff --git a/x-pack/plugins/licensing/server/licensing_checker_route_handler_wrapper.test.ts b/x-pack/plugins/licensing/server/licensing_checker_route_handler_wrapper.test.ts new file mode 100644 index 0000000000000..7bd1cb4e2c883 --- /dev/null +++ b/x-pack/plugins/licensing/server/licensing_checker_route_handler_wrapper.test.ts @@ -0,0 +1,59 @@ +/* + * 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 { httpServerMock } from 'src/core/server/mocks'; + +import { + licenseCheckerRouteHandlerWrapper, + CheckLicense, +} from './license_checker_route_handler_wrapper'; + +const context = { + licensing: { + license: {}, + }, +} as any; +const request = httpServerMock.createKibanaRequest(); + +describe('licenseCheckerRouteHandlerWrapper', () => { + it('calls route handler if checkLicense returns "valid": true', async () => { + const checkLicense: CheckLicense = () => ({ valid: true, message: null }); + const routeHandler = jest.fn(); + const wrapper = licenseCheckerRouteHandlerWrapper(checkLicense, routeHandler); + const response = httpServerMock.createResponseFactory(); + + await wrapper(context, request, response); + + expect(routeHandler).toHaveBeenCalledTimes(1); + expect(routeHandler).toHaveBeenCalledWith(context, request, response); + }); + + it('does not call route handler if checkLicense returns "valid": false', async () => { + const checkLicense: CheckLicense = () => ({ valid: false, message: 'reason' }); + const routeHandler = jest.fn(); + const wrapper = licenseCheckerRouteHandlerWrapper(checkLicense, routeHandler); + const response = httpServerMock.createResponseFactory(); + + await wrapper(context, request, response); + + expect(routeHandler).toHaveBeenCalledTimes(0); + expect(response.forbidden).toHaveBeenCalledTimes(1); + expect(response.forbidden).toHaveBeenCalledWith({ body: 'reason' }); + }); + + it('allows an exception to bubble up if handler throws', async () => { + const checkLicense: CheckLicense = () => ({ valid: true, message: null }); + const routeHandler = () => { + throw new Error('reason'); + }; + const wrapper = licenseCheckerRouteHandlerWrapper(checkLicense, routeHandler); + const response = httpServerMock.createResponseFactory(); + + await expect(wrapper(context, request, response)).rejects.toThrowErrorMatchingInlineSnapshot( + `"reason"` + ); + }); +}); From fa5fe8b6999001038c6b7a7cc83d5c8794e130c7 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Thu, 9 Apr 2020 17:09:23 +0200 Subject: [PATCH 07/13] register logstash route handlers in NP --- x-pack/legacy/plugins/logstash/index.js | 8 --- x-pack/plugins/logstash/kibana.json | 1 + .../lib/check_license/check_license.test.ts | 59 +++++++++++++++++ .../server/lib/check_license/check_license.ts | 65 +++++++++++++++++++ .../server/lib/check_license/index.ts | 7 ++ .../fetch_all_from_scroll.ts | 4 +- .../server/models/pipeline/pipeline.ts | 9 +-- .../pipeline_list_item.test.ts | 3 + .../pipeline_list_item/pipeline_list_item.ts | 17 ++--- x-pack/plugins/logstash/server/plugin.ts | 21 +++++- x-pack/plugins/logstash/server/types.ts | 18 +++++ 11 files changed, 184 insertions(+), 28 deletions(-) create mode 100755 x-pack/plugins/logstash/server/lib/check_license/check_license.test.ts create mode 100644 x-pack/plugins/logstash/server/lib/check_license/check_license.ts create mode 100644 x-pack/plugins/logstash/server/lib/check_license/index.ts create mode 100644 x-pack/plugins/logstash/server/types.ts diff --git a/x-pack/legacy/plugins/logstash/index.js b/x-pack/legacy/plugins/logstash/index.js index fcabcd78705b1..29f01032f3413 100755 --- a/x-pack/legacy/plugins/logstash/index.js +++ b/x-pack/legacy/plugins/logstash/index.js @@ -5,10 +5,6 @@ */ import { resolve } from 'path'; -import { registerLogstashPipelinesRoutes } from './server/routes/api/pipelines'; -import { registerLogstashPipelineRoutes } from './server/routes/api/pipeline'; -import { registerLogstashUpgradeRoutes } from './server/routes/api/upgrade'; -import { registerLogstashClusterRoutes } from './server/routes/api/cluster'; import { registerLicenseChecker } from './server/lib/register_license_checker'; import { PLUGIN } from '../../../plugins/logstash/common/constants'; @@ -32,9 +28,5 @@ export const logstash = kibana => }, init: server => { registerLicenseChecker(server); - registerLogstashPipelinesRoutes(server); - registerLogstashPipelineRoutes(server); - registerLogstashUpgradeRoutes(server); - registerLogstashClusterRoutes(server); }, }); diff --git a/x-pack/plugins/logstash/kibana.json b/x-pack/plugins/logstash/kibana.json index 54fc57625f53b..bcc926535d3c2 100644 --- a/x-pack/plugins/logstash/kibana.json +++ b/x-pack/plugins/logstash/kibana.json @@ -6,6 +6,7 @@ "requiredPlugins": [ "licensing" ], + "optionalPlugins": ["security"], "server": true, "ui": false } diff --git a/x-pack/plugins/logstash/server/lib/check_license/check_license.test.ts b/x-pack/plugins/logstash/server/lib/check_license/check_license.test.ts new file mode 100755 index 0000000000000..6e88b485c471d --- /dev/null +++ b/x-pack/plugins/logstash/server/lib/check_license/check_license.test.ts @@ -0,0 +1,59 @@ +/* + * 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 { licensingMock } from '../../../../licensing/server/mocks'; +import { checkLicense } from './check_license'; + +describe('check_license', function() { + describe('returns "valid": false & message', () => { + it('license information is not available', () => { + const license = licensingMock.createLicenseMock(); + license.isAvailable = false; + + const { valid, message } = checkLicense(license); + + expect(valid).toBe(false); + expect(message).toStrictEqual(expect.any(String)); + }); + + it('license level is not enough', () => { + const license = licensingMock.createLicenseMock(); + license.hasAtLeast.mockReturnValue(false); + + const { valid, message } = checkLicense(license); + + expect(valid).toBe(false); + expect(message).toStrictEqual(expect.any(String)); + }); + + it('license is expired', () => { + const license = licensingMock.createLicenseMock(); + license.isActive = false; + + const { valid, message } = checkLicense(license); + + expect(valid).toBe(false); + expect(message).toStrictEqual(expect.any(String)); + }); + + it('elasticsearch security is disabled', () => { + const license = licensingMock.createLicenseMock(); + license.getFeature.mockReturnValue({ isEnabled: false, isAvailable: false }); + + const { valid, message } = checkLicense(license); + + expect(valid).toBe(false); + expect(message).toStrictEqual(expect.any(String)); + }); + }); + it('returns "valid": true without message otherwise', () => { + const license = licensingMock.createLicenseMock(); + + const { valid, message } = checkLicense(license); + + expect(valid).toBe(true); + expect(message).toBe(null); + }); +}); diff --git a/x-pack/plugins/logstash/server/lib/check_license/check_license.ts b/x-pack/plugins/logstash/server/lib/check_license/check_license.ts new file mode 100644 index 0000000000000..4eef2eb9b0681 --- /dev/null +++ b/x-pack/plugins/logstash/server/lib/check_license/check_license.ts @@ -0,0 +1,65 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +import { CheckLicense } from '../../../../licensing/server'; + +export const checkLicense: CheckLicense = license => { + if (!license.isAvailable) { + return { + valid: false, + message: i18n.translate( + 'xpack.logstash.managementSection.notPossibleToManagePipelinesMessage', + { + defaultMessage: + 'You cannot manage Logstash pipelines because license information is not available at this time.', + } + ), + }; + } + + if (!license.hasAtLeast('standard')) { + return { + valid: false, + message: i18n.translate('xpack.logstash.managementSection.licenseDoesNotSupportDescription', { + defaultMessage: + 'Your {licenseType} license does not support Logstash pipeline management features. Please upgrade your license.', + values: { licenseType: license.type }, + }), + }; + } + + if (!license.isActive) { + return { + valid: false, + message: i18n.translate( + 'xpack.logstash.managementSection.pipelineCrudOperationsNotAllowedDescription', + { + defaultMessage: + 'You cannot edit, create, or delete your Logstash pipelines because your {licenseType} license has expired.', + values: { licenseType: license.type }, + } + ), + }; + } + + if (!license.getFeature('security').isEnabled) { + return { + valid: false, + message: i18n.translate('xpack.logstash.managementSection.enableSecurityDescription', { + defaultMessage: + 'Security must be enabled in order to use Logstash pipeline management features.' + + ' Please set xpack.security.enabled: true in your elasticsearch.yml.', + }), + }; + } + + return { + valid: true, + message: null, + }; +}; diff --git a/x-pack/plugins/logstash/server/lib/check_license/index.ts b/x-pack/plugins/logstash/server/lib/check_license/index.ts new file mode 100644 index 0000000000000..f2c070fd44b6e --- /dev/null +++ b/x-pack/plugins/logstash/server/lib/check_license/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { checkLicense } from './check_license'; diff --git a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts index 57411d7900719..060cf188a4c60 100755 --- a/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts +++ b/x-pack/plugins/logstash/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts @@ -7,14 +7,14 @@ import { APICaller } from 'src/core/server'; import { SearchResponse } from 'elasticsearch'; import { ES_SCROLL_SETTINGS } from '../../../common/constants'; -type Hits = SearchResponse['hits']['hits']; +import { Hits } from '../../types'; export async function fetchAllFromScroll( response: SearchResponse, callWithRequest: APICaller, hits: Hits = [] ): Promise { - const newHits = response.hits.hits; + const newHits = response.hits?.hits || []; const scrollId = response._scroll_id; if (newHits.length > 0) { diff --git a/x-pack/plugins/logstash/server/models/pipeline/pipeline.ts b/x-pack/plugins/logstash/server/models/pipeline/pipeline.ts index f28af33597e64..3f2debeebeb46 100755 --- a/x-pack/plugins/logstash/server/models/pipeline/pipeline.ts +++ b/x-pack/plugins/logstash/server/models/pipeline/pipeline.ts @@ -12,15 +12,15 @@ import { i18n } from '@kbn/i18n'; interface PipelineOptions { id: string; description: string; - username: string; pipeline: string; + username?: string; settings?: Record; } interface DownstreamPipeline { description: string; pipeline: string; - settings: Record; + settings?: Record; } /** * This model deals with a pipeline object from ES and converts it to Kibana downstream @@ -28,9 +28,10 @@ interface DownstreamPipeline { export class Pipeline { public readonly id: string; public readonly description: string; - public readonly username: string; + public readonly username?: string; public readonly pipeline: string; private readonly settings: Record; + constructor(options: PipelineOptions) { this.id = options.id; this.description = options.description; @@ -77,7 +78,7 @@ export class Pipeline { static fromDownstreamJSON( downstreamPipeline: DownstreamPipeline, pipelineId: string, - username: string + username?: string ) { const opts = { id: pipelineId, diff --git a/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.test.ts b/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.test.ts index f909e90ce43ca..c557e84443b02 100755 --- a/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.test.ts +++ b/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.test.ts @@ -20,6 +20,9 @@ describe('pipeline_list_item', () => { username: 'elastic', pipeline: 'input {} filter { grok {} }\n output {}', }, + _index: 'index', + _type: 'type', + _score: 100, }; describe('fromUpstreamJSON factory method', () => { diff --git a/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.ts b/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.ts index 68f91934adf43..98c91fca1fcca 100755 --- a/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.ts +++ b/x-pack/plugins/logstash/server/models/pipeline_list_item/pipeline_list_item.ts @@ -5,18 +5,13 @@ */ import { get } from 'lodash'; +import { Hit, PipelineListItemOptions } from '../../types'; -interface PipelineListItemOptions { - id: string; - description: string; - last_modified: string; - username: string; -} export class PipelineListItem { - private readonly id: string; - private readonly description: string; - private readonly last_modified: string; - private readonly username: string; + public readonly id: string; + public readonly description: string; + public readonly last_modified: string; + public readonly username: string; constructor(options: PipelineListItemOptions) { this.id = options.id; this.description = options.description; @@ -39,7 +34,7 @@ export class PipelineListItem { * Takes the json GET response from ES and constructs a pipeline model to be used * in Kibana downstream */ - static fromUpstreamJSON(pipeline: Record) { + static fromUpstreamJSON(pipeline: Hit) { const opts = { id: pipeline._id, description: get(pipeline, '_source.description'), diff --git a/x-pack/plugins/logstash/server/plugin.ts b/x-pack/plugins/logstash/server/plugin.ts index 903d885c4ecd9..be039427505e9 100644 --- a/x-pack/plugins/logstash/server/plugin.ts +++ b/x-pack/plugins/logstash/server/plugin.ts @@ -3,26 +3,41 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { CoreSetup, Logger, Plugin, PluginInitializerContext } from 'src/core/server'; +import { + CoreSetup, + ICustomClusterClient, + Logger, + Plugin, + PluginInitializerContext, +} from 'src/core/server'; import { LicensingPluginSetup } from '../../licensing/server'; +import { SecurityPluginSetup } from '../../security/server'; import { registerRoutes } from './routes'; interface SetupDeps { licensing: LicensingPluginSetup; + security?: SecurityPluginSetup; } export class LogstashPlugin implements Plugin { private readonly logger: Logger; + private esClient?: ICustomClusterClient; constructor(context: PluginInitializerContext) { this.logger = context.logger.get(); } setup(core: CoreSetup, deps: SetupDeps) { this.logger.debug('Setting up Logstash plugin'); - registerRoutes(core.http.createRouter()); + const esClient = core.elasticsearch.createClient('logstash'); + + registerRoutes(core.http.createRouter(), esClient, deps.security); } start() {} - stop() {} + stop() { + if (this.esClient) { + this.esClient.close(); + } + } } diff --git a/x-pack/plugins/logstash/server/types.ts b/x-pack/plugins/logstash/server/types.ts new file mode 100644 index 0000000000000..63647a07826d3 --- /dev/null +++ b/x-pack/plugins/logstash/server/types.ts @@ -0,0 +1,18 @@ +/* + * 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 { SearchResponse } from 'elasticsearch'; + +type UnwrapArray = T extends Array ? U : T; + +export type Hits = SearchResponse['hits']['hits']; +export type Hit = UnwrapArray; + +export interface PipelineListItemOptions { + id: string; + description: string; + last_modified: string; + username: string; +} From b7037717dc40c2f62ce1f99fc303a9af7e34f445 Mon Sep 17 00:00:00 2001 From: restrry Date: Thu, 9 Apr 2020 18:35:17 +0200 Subject: [PATCH 08/13] track logstash NP i18n --- x-pack/.i18nrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/.i18nrc.json b/x-pack/.i18nrc.json index ae8d61769b14c..eff389cec875a 100644 --- a/x-pack/.i18nrc.json +++ b/x-pack/.i18nrc.json @@ -24,7 +24,7 @@ "xpack.lens": "legacy/plugins/lens", "xpack.licenseMgmt": "plugins/license_management", "xpack.licensing": "plugins/licensing", - "xpack.logstash": "legacy/plugins/logstash", + "xpack.logstash": ["plugins/logstash", "legacy/plugins/logstash"], "xpack.main": "legacy/plugins/xpack_main", "xpack.maps": ["plugins/maps", "legacy/plugins/maps"], "xpack.ml": ["plugins/ml", "legacy/plugins/ml"], From b40ef7190a6ce951d4a0fd1856b664f112681bfa Mon Sep 17 00:00:00 2001 From: restrry Date: Thu, 9 Apr 2020 18:42:05 +0200 Subject: [PATCH 09/13] address shaunak comment --- x-pack/plugins/logstash/server/models/cluster/cluster.test.ts | 2 +- x-pack/plugins/logstash/server/models/cluster/cluster.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/logstash/server/models/cluster/cluster.test.ts b/x-pack/plugins/logstash/server/models/cluster/cluster.test.ts index ceb9e2b5d172c..63f9f1e58f6ec 100755 --- a/x-pack/plugins/logstash/server/models/cluster/cluster.test.ts +++ b/x-pack/plugins/logstash/server/models/cluster/cluster.test.ts @@ -15,7 +15,7 @@ describe('cluster', () => { it('returns correct Cluster instance', () => { const cluster = Cluster.fromUpstreamJSON(upstreamJSON); - expect(cluster.downstreamJSON).toEqual({ uuid: upstreamJSON.cluster_uuid }); + expect(cluster.uuid).toEqual(upstreamJSON.cluster_uuid); }); }); }); diff --git a/x-pack/plugins/logstash/server/models/cluster/cluster.ts b/x-pack/plugins/logstash/server/models/cluster/cluster.ts index c33398a1c6f13..54f03605e14d6 100755 --- a/x-pack/plugins/logstash/server/models/cluster/cluster.ts +++ b/x-pack/plugins/logstash/server/models/cluster/cluster.ts @@ -10,7 +10,7 @@ import { get } from 'lodash'; * This model deals with a cluster object from ES and converts it to Kibana downstream */ export class Cluster { - private readonly uuid: string; + public readonly uuid: string; constructor({ uuid }: { uuid: string }) { this.uuid = uuid; } From 871b3d74e01fedb363f3bddbc72c75e2980dfe97 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Thu, 9 Apr 2020 19:43:36 +0200 Subject: [PATCH 10/13] fix validation --- x-pack/plugins/logstash/server/routes/pipeline/save.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/logstash/server/routes/pipeline/save.ts b/x-pack/plugins/logstash/server/routes/pipeline/save.ts index 23a1a8237a806..f5852d9489c82 100644 --- a/x-pack/plugins/logstash/server/routes/pipeline/save.ts +++ b/x-pack/plugins/logstash/server/routes/pipeline/save.ts @@ -30,7 +30,7 @@ export function registerPipelineSaveRoute( description: schema.string(), pipeline: schema.string(), username: schema.string(), - settings: schema.maybe(schema.object({}, { unknowns: 'ignore' })), + settings: schema.maybe(schema.object({}, { unknowns: 'allow' })), }), }, }, From 1d85d54f5344014457fef113f22ed85bf15b8bdb Mon Sep 17 00:00:00 2001 From: restrry Date: Tue, 14 Apr 2020 09:04:44 +0200 Subject: [PATCH 11/13] udpdate security tests since for new mock defaults --- .../common/licensing/license_service.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/security/common/licensing/license_service.test.ts b/x-pack/plugins/security/common/licensing/license_service.test.ts index dfc94042ef930..5bdfa7d4886aa 100644 --- a/x-pack/plugins/security/common/licensing/license_service.test.ts +++ b/x-pack/plugins/security/common/licensing/license_service.test.ts @@ -78,14 +78,14 @@ describe('license features', function() { expect(subscriptionHandler.mock.calls[1]).toMatchInlineSnapshot(` Array [ Object { - "allowLogin": false, - "allowRbac": false, - "allowRoleDocumentLevelSecurity": false, - "allowRoleFieldLevelSecurity": false, - "allowSubFeaturePrivileges": false, - "showLinks": false, - "showLogin": false, - "showRoleMappingsManagement": false, + "allowLogin": true, + "allowRbac": true, + "allowRoleDocumentLevelSecurity": true, + "allowRoleFieldLevelSecurity": true, + "allowSubFeaturePrivileges": true, + "showLinks": true, + "showLogin": true, + "showRoleMappingsManagement": true, }, ] `); From de1a53773f0e8859df2ce632afb3b7a554b931a2 Mon Sep 17 00:00:00 2001 From: restrry Date: Tue, 14 Apr 2020 15:23:04 +0200 Subject: [PATCH 12/13] address Pierres comments --- x-pack/plugins/licensing/server/index.ts | 5 +-- ... => wrap_route_with_license_check.test.ts} | 28 +++++++++---- ...er.ts => wrap_route_with_license_check.ts} | 2 +- .../lib/check_license/check_license.test.ts | 3 +- x-pack/plugins/logstash/server/plugin.ts | 14 +++++-- .../logstash/server/routes/cluster/load.ts | 39 +++++++++---------- .../plugins/logstash/server/routes/index.ts | 22 +++++------ .../logstash/server/routes/pipeline/delete.ts | 10 ++--- .../logstash/server/routes/pipeline/load.ts | 10 ++--- .../logstash/server/routes/pipeline/save.ts | 14 +++---- .../server/routes/pipelines/delete.ts | 10 ++--- .../logstash/server/routes/pipelines/list.ts | 10 ++--- .../logstash/server/routes/upgrade/execute.ts | 10 ++--- x-pack/plugins/logstash/server/types.ts | 11 +++++- 14 files changed, 102 insertions(+), 86 deletions(-) rename x-pack/plugins/licensing/server/{licensing_checker_route_handler_wrapper.test.ts => wrap_route_with_license_check.test.ts} (66%) rename x-pack/plugins/licensing/server/{license_checker_route_handler_wrapper.ts => wrap_route_with_license_check.ts} (94%) diff --git a/x-pack/plugins/licensing/server/index.ts b/x-pack/plugins/licensing/server/index.ts index 1f95459513814..76e65afc595c4 100644 --- a/x-pack/plugins/licensing/server/index.ts +++ b/x-pack/plugins/licensing/server/index.ts @@ -12,7 +12,4 @@ export const plugin = (context: PluginInitializerContext) => new LicensingPlugin export * from '../common/types'; export * from './types'; export { config } from './licensing_config'; -export { - CheckLicense, - licenseCheckerRouteHandlerWrapper, -} from './license_checker_route_handler_wrapper'; +export { CheckLicense, wrapRouteWithLicenseCheck } from './wrap_route_with_license_check'; diff --git a/x-pack/plugins/licensing/server/licensing_checker_route_handler_wrapper.test.ts b/x-pack/plugins/licensing/server/wrap_route_with_license_check.test.ts similarity index 66% rename from x-pack/plugins/licensing/server/licensing_checker_route_handler_wrapper.test.ts rename to x-pack/plugins/licensing/server/wrap_route_with_license_check.test.ts index 7bd1cb4e2c883..7abdd3f6190ce 100644 --- a/x-pack/plugins/licensing/server/licensing_checker_route_handler_wrapper.test.ts +++ b/x-pack/plugins/licensing/server/wrap_route_with_license_check.test.ts @@ -6,10 +6,7 @@ import { httpServerMock } from 'src/core/server/mocks'; -import { - licenseCheckerRouteHandlerWrapper, - CheckLicense, -} from './license_checker_route_handler_wrapper'; +import { wrapRouteWithLicenseCheck, CheckLicense } from './wrap_route_with_license_check'; const context = { licensing: { @@ -18,11 +15,11 @@ const context = { } as any; const request = httpServerMock.createKibanaRequest(); -describe('licenseCheckerRouteHandlerWrapper', () => { +describe('wrapRouteWithLicenseCheck', () => { it('calls route handler if checkLicense returns "valid": true', async () => { const checkLicense: CheckLicense = () => ({ valid: true, message: null }); const routeHandler = jest.fn(); - const wrapper = licenseCheckerRouteHandlerWrapper(checkLicense, routeHandler); + const wrapper = wrapRouteWithLicenseCheck(checkLicense, routeHandler); const response = httpServerMock.createResponseFactory(); await wrapper(context, request, response); @@ -34,7 +31,7 @@ describe('licenseCheckerRouteHandlerWrapper', () => { it('does not call route handler if checkLicense returns "valid": false', async () => { const checkLicense: CheckLicense = () => ({ valid: false, message: 'reason' }); const routeHandler = jest.fn(); - const wrapper = licenseCheckerRouteHandlerWrapper(checkLicense, routeHandler); + const wrapper = wrapRouteWithLicenseCheck(checkLicense, routeHandler); const response = httpServerMock.createResponseFactory(); await wrapper(context, request, response); @@ -49,11 +46,26 @@ describe('licenseCheckerRouteHandlerWrapper', () => { const routeHandler = () => { throw new Error('reason'); }; - const wrapper = licenseCheckerRouteHandlerWrapper(checkLicense, routeHandler); + const wrapper = wrapRouteWithLicenseCheck(checkLicense, routeHandler); const response = httpServerMock.createResponseFactory(); await expect(wrapper(context, request, response)).rejects.toThrowErrorMatchingInlineSnapshot( `"reason"` ); }); + + it('allows an exception to bubble up if "checkLicense" throws', async () => { + const checkLicense: CheckLicense = () => { + throw new Error('reason'); + }; + const routeHandler = jest.fn(); + const wrapper = wrapRouteWithLicenseCheck(checkLicense, routeHandler); + const response = httpServerMock.createResponseFactory(); + + await expect(wrapper(context, request, response)).rejects.toThrowErrorMatchingInlineSnapshot( + `"reason"` + ); + + expect(routeHandler).toHaveBeenCalledTimes(0); + }); }); diff --git a/x-pack/plugins/licensing/server/license_checker_route_handler_wrapper.ts b/x-pack/plugins/licensing/server/wrap_route_with_license_check.ts similarity index 94% rename from x-pack/plugins/licensing/server/license_checker_route_handler_wrapper.ts rename to x-pack/plugins/licensing/server/wrap_route_with_license_check.ts index 7f07a054c41b7..e0cac8d9db208 100644 --- a/x-pack/plugins/licensing/server/license_checker_route_handler_wrapper.ts +++ b/x-pack/plugins/licensing/server/wrap_route_with_license_check.ts @@ -18,7 +18,7 @@ export type CheckLicense = ( license: ILicense ) => { valid: false; message: string } | { valid: true; message: null }; -export function licenseCheckerRouteHandlerWrapper( +export function wrapRouteWithLicenseCheck( checkLicense: CheckLicense, handler: RequestHandler ): RequestHandler { diff --git a/x-pack/plugins/logstash/server/lib/check_license/check_license.test.ts b/x-pack/plugins/logstash/server/lib/check_license/check_license.test.ts index 6e88b485c471d..324e0a22ff378 100755 --- a/x-pack/plugins/logstash/server/lib/check_license/check_license.test.ts +++ b/x-pack/plugins/logstash/server/lib/check_license/check_license.test.ts @@ -7,7 +7,7 @@ import { licensingMock } from '../../../../licensing/server/mocks'; import { checkLicense } from './check_license'; describe('check_license', function() { - describe('returns "valid": false & message', () => { + describe('returns "valid": false & message when', () => { it('license information is not available', () => { const license = licensingMock.createLicenseMock(); license.isAvailable = false; @@ -48,6 +48,7 @@ describe('check_license', function() { expect(message).toStrictEqual(expect.any(String)); }); }); + it('returns "valid": true without message otherwise', () => { const license = licensingMock.createLicenseMock(); diff --git a/x-pack/plugins/logstash/server/plugin.ts b/x-pack/plugins/logstash/server/plugin.ts index be039427505e9..c048dd13bfb0c 100644 --- a/x-pack/plugins/logstash/server/plugin.ts +++ b/x-pack/plugins/logstash/server/plugin.ts @@ -5,6 +5,7 @@ */ import { CoreSetup, + CoreStart, ICustomClusterClient, Logger, Plugin, @@ -23,18 +24,25 @@ interface SetupDeps { export class LogstashPlugin implements Plugin { private readonly logger: Logger; private esClient?: ICustomClusterClient; + private coreSetup?: CoreSetup; constructor(context: PluginInitializerContext) { this.logger = context.logger.get(); } setup(core: CoreSetup, deps: SetupDeps) { this.logger.debug('Setting up Logstash plugin'); - const esClient = core.elasticsearch.createClient('logstash'); - registerRoutes(core.http.createRouter(), esClient, deps.security); + this.coreSetup = core; + registerRoutes(core.http.createRouter(), deps.security); } - start() {} + start(core: CoreStart) { + const esClient = core.elasticsearch.legacy.createClient('logstash'); + + this.coreSetup!.http.registerRouteHandlerContext('logstash', async (context, request) => { + return { esClient: esClient.asScoped(request) }; + }); + } stop() { if (this.esClient) { this.esClient.close(); diff --git a/x-pack/plugins/logstash/server/routes/cluster/load.ts b/x-pack/plugins/logstash/server/routes/cluster/load.ts index 19f207bb5ea61..18fe21f3da675 100644 --- a/x-pack/plugins/logstash/server/routes/cluster/load.ts +++ b/x-pack/plugins/logstash/server/routes/cluster/load.ts @@ -3,35 +3,32 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { ICustomClusterClient, IRouter } from 'src/core/server'; -import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; +import { IRouter } from 'src/core/server'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; import { Cluster } from '../../models/cluster'; import { checkLicense } from '../../lib/check_license'; -export function registerClusterLoadRoute(router: IRouter, esClient: ICustomClusterClient) { +export function registerClusterLoadRoute(router: IRouter) { router.get( { path: '/api/logstash/cluster', validate: false, }, - licenseCheckerRouteHandlerWrapper( - checkLicense, - router.handleLegacyErrors(async (context, request, response) => { - try { - const client = esClient.asScoped(request); - const info = await client.callAsCurrentUser('info'); - return response.ok({ - body: { - cluster: Cluster.fromUpstreamJSON(info).downstreamJSON, - }, - }); - } catch (err) { - if (err.status === 403) { - return response.ok(); - } - return response.internalError(); + wrapRouteWithLicenseCheck(checkLicense, async (context, request, response) => { + try { + const client = context.logstash!.esClient; + const info = await client.callAsCurrentUser('info'); + return response.ok({ + body: { + cluster: Cluster.fromUpstreamJSON(info).downstreamJSON, + }, + }); + } catch (err) { + if (err.status === 403) { + return response.ok(); } - }) - ) + return response.internalError(); + } + }) ); } diff --git a/x-pack/plugins/logstash/server/routes/index.ts b/x-pack/plugins/logstash/server/routes/index.ts index 771ef83e49b21..0c7183b409055 100644 --- a/x-pack/plugins/logstash/server/routes/index.ts +++ b/x-pack/plugins/logstash/server/routes/index.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { IRouter, ICustomClusterClient } from 'src/core/server'; +import { IRouter } from 'src/core/server'; import { SecurityPluginSetup } from '../../../security/server'; import { registerClusterLoadRoute } from './cluster'; import { @@ -14,19 +14,15 @@ import { import { registerPipelinesListRoute, registerPipelinesDeleteRoute } from './pipelines'; import { registerUpgradeRoute } from './upgrade'; -export function registerRoutes( - router: IRouter, - esClient: ICustomClusterClient, - security?: SecurityPluginSetup -) { - registerClusterLoadRoute(router, esClient); +export function registerRoutes(router: IRouter, security?: SecurityPluginSetup) { + registerClusterLoadRoute(router); - registerPipelineDeleteRoute(router, esClient); - registerPipelineLoadRoute(router, esClient); - registerPipelineSaveRoute(router, esClient, security); + registerPipelineDeleteRoute(router); + registerPipelineLoadRoute(router); + registerPipelineSaveRoute(router, security); - registerPipelinesListRoute(router, esClient); - registerPipelinesDeleteRoute(router, esClient); + registerPipelinesListRoute(router); + registerPipelinesDeleteRoute(router); - registerUpgradeRoute(router, esClient); + registerUpgradeRoute(router); } diff --git a/x-pack/plugins/logstash/server/routes/pipeline/delete.ts b/x-pack/plugins/logstash/server/routes/pipeline/delete.ts index 73c1029dd3273..4aeae3e0ae2d5 100644 --- a/x-pack/plugins/logstash/server/routes/pipeline/delete.ts +++ b/x-pack/plugins/logstash/server/routes/pipeline/delete.ts @@ -4,13 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; -import { ICustomClusterClient, IRouter } from 'src/core/server'; +import { IRouter } from 'src/core/server'; import { INDEX_NAMES } from '../../../common/constants'; -import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; import { checkLicense } from '../../lib/check_license'; -export function registerPipelineDeleteRoute(router: IRouter, esClient: ICustomClusterClient) { +export function registerPipelineDeleteRoute(router: IRouter) { router.delete( { path: '/api/logstash/pipeline/{id}', @@ -20,10 +20,10 @@ export function registerPipelineDeleteRoute(router: IRouter, esClient: ICustomCl }), }, }, - licenseCheckerRouteHandlerWrapper( + wrapRouteWithLicenseCheck( checkLicense, router.handleLegacyErrors(async (context, request, response) => { - const client = esClient.asScoped(request); + const client = context.logstash!.esClient; await client.callAsCurrentUser('delete', { index: INDEX_NAMES.PIPELINES, diff --git a/x-pack/plugins/logstash/server/routes/pipeline/load.ts b/x-pack/plugins/logstash/server/routes/pipeline/load.ts index cfc1a92864213..fec9097114d26 100644 --- a/x-pack/plugins/logstash/server/routes/pipeline/load.ts +++ b/x-pack/plugins/logstash/server/routes/pipeline/load.ts @@ -4,14 +4,14 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; -import { ICustomClusterClient, IRouter } from 'src/core/server'; +import { IRouter } from 'src/core/server'; import { INDEX_NAMES } from '../../../common/constants'; import { Pipeline } from '../../models/pipeline'; -import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; import { checkLicense } from '../../lib/check_license'; -export function registerPipelineLoadRoute(router: IRouter, esClient: ICustomClusterClient) { +export function registerPipelineLoadRoute(router: IRouter) { router.get( { path: '/api/logstash/pipeline/{id}', @@ -21,10 +21,10 @@ export function registerPipelineLoadRoute(router: IRouter, esClient: ICustomClus }), }, }, - licenseCheckerRouteHandlerWrapper( + wrapRouteWithLicenseCheck( checkLicense, router.handleLegacyErrors(async (context, request, response) => { - const client = esClient.asScoped(request); + const client = context.logstash!.esClient; const result = await client.callAsCurrentUser('get', { index: INDEX_NAMES.PIPELINES, diff --git a/x-pack/plugins/logstash/server/routes/pipeline/save.ts b/x-pack/plugins/logstash/server/routes/pipeline/save.ts index f5852d9489c82..556c281944a85 100644 --- a/x-pack/plugins/logstash/server/routes/pipeline/save.ts +++ b/x-pack/plugins/logstash/server/routes/pipeline/save.ts @@ -5,19 +5,15 @@ */ import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; -import { ICustomClusterClient, IRouter } from 'src/core/server'; +import { IRouter } from 'src/core/server'; import { INDEX_NAMES } from '../../../common/constants'; import { Pipeline } from '../../models/pipeline'; -import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; import { SecurityPluginSetup } from '../../../../security/server'; import { checkLicense } from '../../lib/check_license'; -export function registerPipelineSaveRoute( - router: IRouter, - esClient: ICustomClusterClient, - security?: SecurityPluginSetup -) { +export function registerPipelineSaveRoute(router: IRouter, security?: SecurityPluginSetup) { router.put( { path: '/api/logstash/pipeline/{id}', @@ -34,7 +30,7 @@ export function registerPipelineSaveRoute( }), }, }, - licenseCheckerRouteHandlerWrapper( + wrapRouteWithLicenseCheck( checkLicense, router.handleLegacyErrors(async (context, request, response) => { try { @@ -44,7 +40,7 @@ export function registerPipelineSaveRoute( username = user?.username; } - const client = esClient.asScoped(request); + const client = context.logstash!.esClient; const pipeline = Pipeline.fromDownstreamJSON(request.body, request.params.id, username); await client.callAsCurrentUser('index', { diff --git a/x-pack/plugins/logstash/server/routes/pipelines/delete.ts b/x-pack/plugins/logstash/server/routes/pipelines/delete.ts index 5e2e6ef3d77c2..ac3097ac0424b 100644 --- a/x-pack/plugins/logstash/server/routes/pipelines/delete.ts +++ b/x-pack/plugins/logstash/server/routes/pipelines/delete.ts @@ -4,8 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import { schema } from '@kbn/config-schema'; -import { APICaller, ICustomClusterClient, IRouter } from 'src/core/server'; -import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; +import { APICaller, IRouter } from 'src/core/server'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; import { INDEX_NAMES } from '../../../common/constants'; import { checkLicense } from '../../lib/check_license'; @@ -31,7 +31,7 @@ async function deletePipelines(callWithRequest: APICaller, pipelineIds: string[] }; } -export function registerPipelinesDeleteRoute(router: IRouter, esClient: ICustomClusterClient) { +export function registerPipelinesDeleteRoute(router: IRouter) { router.post( { path: '/api/logstash/pipelines/delete', @@ -41,10 +41,10 @@ export function registerPipelinesDeleteRoute(router: IRouter, esClient: ICustomC }), }, }, - licenseCheckerRouteHandlerWrapper( + wrapRouteWithLicenseCheck( checkLicense, router.handleLegacyErrors(async (context, request, response) => { - const client = esClient.asScoped(request); + const client = context.logstash!.esClient; const results = await deletePipelines(client.callAsCurrentUser, request.body.pipelineIds); return response.ok({ body: { results } }); diff --git a/x-pack/plugins/logstash/server/routes/pipelines/list.ts b/x-pack/plugins/logstash/server/routes/pipelines/list.ts index eaa4a49b93aeb..bc477a25a7988 100644 --- a/x-pack/plugins/logstash/server/routes/pipelines/list.ts +++ b/x-pack/plugins/logstash/server/routes/pipelines/list.ts @@ -5,8 +5,8 @@ */ import { i18n } from '@kbn/i18n'; import { SearchResponse } from 'elasticsearch'; -import { APICaller, ICustomClusterClient, IRouter } from 'src/core/server'; -import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; +import { APICaller, IRouter } from 'src/core/server'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; import { INDEX_NAMES, ES_SCROLL_SETTINGS } from '../../../common/constants'; import { PipelineListItem } from '../../models/pipeline_list_item'; @@ -27,17 +27,17 @@ async function fetchPipelines(callWithRequest: APICaller) { return fetchAllFromScroll(response, callWithRequest); } -export function registerPipelinesListRoute(router: IRouter, esClient: ICustomClusterClient) { +export function registerPipelinesListRoute(router: IRouter) { router.get( { path: '/api/logstash/pipelines', validate: false, }, - licenseCheckerRouteHandlerWrapper( + wrapRouteWithLicenseCheck( checkLicense, router.handleLegacyErrors(async (context, request, response) => { try { - const client = esClient.asScoped(request); + const client = context.logstash!.esClient; const pipelinesHits = await fetchPipelines(client.callAsCurrentUser); const pipelines = pipelinesHits.map(pipeline => { diff --git a/x-pack/plugins/logstash/server/routes/upgrade/execute.ts b/x-pack/plugins/logstash/server/routes/upgrade/execute.ts index e844830379f88..2bd2c0f89e190 100644 --- a/x-pack/plugins/logstash/server/routes/upgrade/execute.ts +++ b/x-pack/plugins/logstash/server/routes/upgrade/execute.ts @@ -3,22 +3,22 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { ICustomClusterClient, IRouter } from 'src/core/server'; -import { licenseCheckerRouteHandlerWrapper } from '../../../../licensing/server'; +import { IRouter } from 'src/core/server'; +import { wrapRouteWithLicenseCheck } from '../../../../licensing/server'; import { INDEX_NAMES } from '../../../common/constants'; import { checkLicense } from '../../lib/check_license'; -export function registerUpgradeRoute(router: IRouter, esClient: ICustomClusterClient) { +export function registerUpgradeRoute(router: IRouter) { router.post( { path: '/api/logstash/upgrade', validate: false, }, - licenseCheckerRouteHandlerWrapper( + wrapRouteWithLicenseCheck( checkLicense, router.handleLegacyErrors(async (context, request, response) => { - const client = esClient.asScoped(request); + const client = context.logstash!.esClient; const doesIndexExist = await client.callAsCurrentUser('indices.exists', { index: INDEX_NAMES.PIPELINES, diff --git a/x-pack/plugins/logstash/server/types.ts b/x-pack/plugins/logstash/server/types.ts index 63647a07826d3..2b266b2f27708 100644 --- a/x-pack/plugins/logstash/server/types.ts +++ b/x-pack/plugins/logstash/server/types.ts @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ import { SearchResponse } from 'elasticsearch'; +import { IScopedClusterClient } from 'src/core/server'; -type UnwrapArray = T extends Array ? U : T; +type UnwrapArray = T extends Array ? U : never; export type Hits = SearchResponse['hits']['hits']; export type Hit = UnwrapArray; @@ -16,3 +17,11 @@ export interface PipelineListItemOptions { last_modified: string; username: string; } + +declare module 'src/core/server' { + interface RequestHandlerContext { + logstash?: { + esClient: IScopedClusterClient; + }; + } +} From 8344876ead2f58ae9d5c15e30c331ea42fec1b3f Mon Sep 17 00:00:00 2001 From: restrry Date: Tue, 14 Apr 2020 15:56:06 +0200 Subject: [PATCH 13/13] rename upgrade file route --- x-pack/plugins/logstash/server/routes/upgrade/index.ts | 2 +- .../logstash/server/routes/upgrade/{execute.ts => upgrade.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename x-pack/plugins/logstash/server/routes/upgrade/{execute.ts => upgrade.ts} (100%) diff --git a/x-pack/plugins/logstash/server/routes/upgrade/index.ts b/x-pack/plugins/logstash/server/routes/upgrade/index.ts index b2e65aece4dc6..3a5b0868b446b 100644 --- a/x-pack/plugins/logstash/server/routes/upgrade/index.ts +++ b/x-pack/plugins/logstash/server/routes/upgrade/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { registerUpgradeRoute } from './execute'; +export { registerUpgradeRoute } from './upgrade'; diff --git a/x-pack/plugins/logstash/server/routes/upgrade/execute.ts b/x-pack/plugins/logstash/server/routes/upgrade/upgrade.ts similarity index 100% rename from x-pack/plugins/logstash/server/routes/upgrade/execute.ts rename to x-pack/plugins/logstash/server/routes/upgrade/upgrade.ts