From 0021d90befbbd1f2ebdaabb6040435d4c9329cba Mon Sep 17 00:00:00 2001 From: Alison Goryachev Date: Wed, 5 Feb 2020 11:46:53 -0500 Subject: [PATCH] move server code out of legacy and integrate NP license plugin --- .../legacy/plugins/remote_clusters/index.ts | 17 +-- .../app/store/actions/remove_clusters.js | 2 +- .../license_pre_routing_factory.ts | 43 ------ .../plugins/remote_clusters/server/plugin.ts | 53 ------- .../remote_clusters/common/constants.ts | 23 +++ .../common/lib/cluster_serialization.test.ts | 137 ++++++++++++++++++ .../common/lib/cluster_serialization.ts | 71 +++++++++ .../remote_clusters/common/lib}/index.ts | 3 +- .../plugins/remote_clusters/kibana.json | 4 +- .../plugins/remote_clusters/server/index.ts | 9 ++ .../call_with_request_factory.ts | 0 .../lib/call_with_request_factory/index.ts | 0 .../server/lib/does_cluster_exist.ts | 0 .../server/lib/is_es_error/index.ts | 0 .../server/lib/is_es_error/is_es_error.ts | 0 .../lib/license_pre_routing_factory/index.ts | 0 .../license_pre_routing_factory.test.ts} | 44 ++---- .../license_pre_routing_factory.ts | 35 +++++ .../plugins/remote_clusters/server/plugin.ts | 72 +++++++++ .../server/routes/api/add_route.test.ts | 0 .../server/routes/api/add_route.ts | 12 +- .../server/routes/api/delete_route.test.ts | 0 .../server/routes/api/delete_route.ts | 12 +- .../server/routes/api/get_route.test.ts | 0 .../server/routes/api/get_route.ts | 12 +- .../server/routes/api/index.ts | 0 .../server/routes/api/update_route.test.ts | 0 .../server/routes/api/update_route.ts | 12 +- .../plugins/remote_clusters/server/types.ts | 18 ++- 29 files changed, 396 insertions(+), 183 deletions(-) delete mode 100644 x-pack/legacy/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts delete mode 100644 x-pack/legacy/plugins/remote_clusters/server/plugin.ts create mode 100644 x-pack/plugins/remote_clusters/common/constants.ts create mode 100644 x-pack/plugins/remote_clusters/common/lib/cluster_serialization.test.ts create mode 100644 x-pack/plugins/remote_clusters/common/lib/cluster_serialization.ts rename x-pack/{legacy/plugins/remote_clusters/server => plugins/remote_clusters/common/lib}/index.ts (67%) rename x-pack/{legacy => }/plugins/remote_clusters/kibana.json (76%) create mode 100644 x-pack/plugins/remote_clusters/server/index.ts rename x-pack/{legacy => }/plugins/remote_clusters/server/lib/call_with_request_factory/call_with_request_factory.ts (100%) rename x-pack/{legacy => }/plugins/remote_clusters/server/lib/call_with_request_factory/index.ts (100%) rename x-pack/{legacy => }/plugins/remote_clusters/server/lib/does_cluster_exist.ts (100%) rename x-pack/{legacy => }/plugins/remote_clusters/server/lib/is_es_error/index.ts (100%) rename x-pack/{legacy => }/plugins/remote_clusters/server/lib/is_es_error/is_es_error.ts (100%) rename x-pack/{legacy => }/plugins/remote_clusters/server/lib/license_pre_routing_factory/index.ts (100%) rename x-pack/{legacy/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.test.js => plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.test.ts} (53%) create mode 100644 x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts create mode 100644 x-pack/plugins/remote_clusters/server/plugin.ts rename x-pack/{legacy => }/plugins/remote_clusters/server/routes/api/add_route.test.ts (100%) rename x-pack/{legacy => }/plugins/remote_clusters/server/routes/api/add_route.ts (87%) rename x-pack/{legacy => }/plugins/remote_clusters/server/routes/api/delete_route.test.ts (100%) rename x-pack/{legacy => }/plugins/remote_clusters/server/routes/api/delete_route.ts (90%) rename x-pack/{legacy => }/plugins/remote_clusters/server/routes/api/get_route.test.ts (100%) rename x-pack/{legacy => }/plugins/remote_clusters/server/routes/api/get_route.ts (83%) rename x-pack/{legacy => }/plugins/remote_clusters/server/routes/api/index.ts (100%) rename x-pack/{legacy => }/plugins/remote_clusters/server/routes/api/update_route.test.ts (100%) rename x-pack/{legacy => }/plugins/remote_clusters/server/routes/api/update_route.ts (90%) rename x-pack/{legacy => }/plugins/remote_clusters/server/types.ts (63%) diff --git a/x-pack/legacy/plugins/remote_clusters/index.ts b/x-pack/legacy/plugins/remote_clusters/index.ts index a758b8452e711..5dd823e09eb8b 100644 --- a/x-pack/legacy/plugins/remote_clusters/index.ts +++ b/x-pack/legacy/plugins/remote_clusters/index.ts @@ -7,7 +7,6 @@ import { Legacy } from 'kibana'; import { resolve } from 'path'; import { PLUGIN } from './common'; -import { plugin } from './server'; export function remoteClusters(kibana: any) { return new kibana.Plugin({ @@ -42,20 +41,6 @@ export function remoteClusters(kibana: any) { config.get('xpack.remote_clusters.enabled') && config.get('xpack.index_management.enabled') ); }, - init(server: any) { - const { core: coreSetup } = server.newPlatform.setup; - - const remoteClustersPluginInstance = plugin(); - - remoteClustersPluginInstance.setup(coreSetup, { - __LEGACY: { - route: server.route.bind(server), - plugins: { - xpack_main: server.plugins.xpack_main, - remote_clusters: server.plugins[PLUGIN.ID], - }, - }, - }); - }, + init(server: any) {}, }); } diff --git a/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/remove_clusters.js b/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/remove_clusters.js index 47eb192714d7a..e41c10e001be4 100644 --- a/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/remove_clusters.js +++ b/x-pack/legacy/plugins/remote_clusters/public/app/store/actions/remove_clusters.js @@ -64,7 +64,7 @@ export const removeClusters = names => async (dispatch, getState) => { name, error: { output: { - payload: { message }, + payload: { msg: message }, }, }, } = errors[0]; diff --git a/x-pack/legacy/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts b/x-pack/legacy/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts deleted file mode 100644 index 353510d96a00d..0000000000000 --- a/x-pack/legacy/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts +++ /dev/null @@ -1,43 +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 { - KibanaRequest, - KibanaResponseFactory, - RequestHandler, - RequestHandlerContext, -} from 'src/core/server'; -import { PLUGIN } from '../../../common'; -import { LICENSE_STATUS_VALID } from '../../../../../common/constants/license_status'; -import { ServerShim } from '../../types'; - -export const licensePreRoutingFactory = ( - server: ServerShim, - handler: RequestHandler -): RequestHandler => { - const xpackMainPlugin = server.plugins.xpack_main; - - // License checking and enable/disable logic - return function licensePreRouting( - ctx: RequestHandlerContext, - request: KibanaRequest, - response: KibanaResponseFactory - ) { - const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults(); - const { status } = licenseCheckResults; - - if (status !== LICENSE_STATUS_VALID) { - return response.customError({ - body: { - message: licenseCheckResults.messsage, - }, - statusCode: 403, - }); - } - - return handler(ctx, request, response); - }; -}; diff --git a/x-pack/legacy/plugins/remote_clusters/server/plugin.ts b/x-pack/legacy/plugins/remote_clusters/server/plugin.ts deleted file mode 100644 index 50a96eb30997b..0000000000000 --- a/x-pack/legacy/plugins/remote_clusters/server/plugin.ts +++ /dev/null @@ -1,53 +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 { CoreSetup, Plugin } from 'src/core/server'; - -import { registerLicenseChecker } from '../../../server/lib/register_license_checker'; -import { PLUGIN } from '../common'; -import { ServerShim, RouteDependencies } from './types'; - -import { - registerGetRoute, - registerAddRoute, - registerUpdateRoute, - registerDeleteRoute, -} from './routes/api'; - -export class RemoteClustersServerPlugin implements Plugin { - async setup( - { http, elasticsearch: elasticsearchService }: CoreSetup, - { - __LEGACY: serverShim, - }: { - __LEGACY: ServerShim; - } - ) { - const elasticsearch = await elasticsearchService.adminClient; - const router = http.createRouter(); - const routeDependencies: RouteDependencies = { - elasticsearch, - elasticsearchService, - router, - }; - - registerLicenseChecker( - serverShim as any, - PLUGIN.ID, - PLUGIN.getI18nName(), - PLUGIN.MINIMUM_LICENSE_REQUIRED - ); - - // Register routes. - registerGetRoute(routeDependencies, serverShim); - registerAddRoute(routeDependencies, serverShim); - registerUpdateRoute(routeDependencies, serverShim); - registerDeleteRoute(routeDependencies, serverShim); - } - - start() {} - - stop() {} -} diff --git a/x-pack/plugins/remote_clusters/common/constants.ts b/x-pack/plugins/remote_clusters/common/constants.ts new file mode 100644 index 0000000000000..3521b7f662fc9 --- /dev/null +++ b/x-pack/plugins/remote_clusters/common/constants.ts @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { i18n } from '@kbn/i18n'; +import { LicenseType } from '../../licensing/common/types'; + +const basicLicense: LicenseType = 'basic'; + +export const PLUGIN = { + id: 'remote_clusters', + // Remote Clusters are used in both CCS and CCR, and CCS is available for all licenses. + minimumLicenseType: basicLicense, + getI18nName: (): string => { + return i18n.translate('xpack.remoteClusters.appName', { + defaultMessage: 'Remote Clusters', + }); + }, +}; + +export const API_BASE_PATH = '/api/remote_clusters'; diff --git a/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.test.ts b/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.test.ts new file mode 100644 index 0000000000000..476fbee7fb6a0 --- /dev/null +++ b/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.test.ts @@ -0,0 +1,137 @@ +/* + * 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 { deserializeCluster, serializeCluster } from './cluster_serialization'; + +describe('cluster_serialization', () => { + describe('deserializeCluster()', () => { + it('should throw an error for invalid arguments', () => { + expect(() => deserializeCluster('foo', 'bar')).toThrowError(); + }); + + it('should deserialize a complete cluster object', () => { + expect( + deserializeCluster('test_cluster', { + seeds: ['localhost:9300'], + connected: true, + num_nodes_connected: 1, + max_connections_per_cluster: 3, + initial_connect_timeout: '30s', + skip_unavailable: false, + transport: { + ping_schedule: '-1', + compress: false, + }, + }) + ).toEqual({ + name: 'test_cluster', + seeds: ['localhost:9300'], + isConnected: true, + connectedNodesCount: 1, + maxConnectionsPerCluster: 3, + initialConnectTimeout: '30s', + skipUnavailable: false, + transportPingSchedule: '-1', + transportCompress: false, + }); + }); + + it('should deserialize a cluster object without transport information', () => { + expect( + deserializeCluster('test_cluster', { + seeds: ['localhost:9300'], + connected: true, + num_nodes_connected: 1, + max_connections_per_cluster: 3, + initial_connect_timeout: '30s', + skip_unavailable: false, + }) + ).toEqual({ + name: 'test_cluster', + seeds: ['localhost:9300'], + isConnected: true, + connectedNodesCount: 1, + maxConnectionsPerCluster: 3, + initialConnectTimeout: '30s', + skipUnavailable: false, + }); + }); + + it('should deserialize a cluster object with arbitrary missing properties', () => { + expect( + deserializeCluster('test_cluster', { + seeds: ['localhost:9300'], + connected: true, + num_nodes_connected: 1, + initial_connect_timeout: '30s', + transport: { + compress: false, + }, + }) + ).toEqual({ + name: 'test_cluster', + seeds: ['localhost:9300'], + isConnected: true, + connectedNodesCount: 1, + initialConnectTimeout: '30s', + transportCompress: false, + }); + }); + }); + + describe('serializeCluster()', () => { + it('should throw an error for invalid arguments', () => { + expect(() => serializeCluster('foo')).toThrowError(); + }); + + it('should serialize a complete cluster object to only dynamic properties', () => { + expect( + serializeCluster({ + name: 'test_cluster', + seeds: ['localhost:9300'], + isConnected: true, + connectedNodesCount: 1, + maxConnectionsPerCluster: 3, + initialConnectTimeout: '30s', + skipUnavailable: false, + transportPingSchedule: '-1', + transportCompress: false, + }) + ).toEqual({ + persistent: { + cluster: { + remote: { + test_cluster: { + seeds: ['localhost:9300'], + skip_unavailable: false, + }, + }, + }, + }, + }); + }); + + it('should serialize a cluster object with missing properties', () => { + expect( + serializeCluster({ + name: 'test_cluster', + seeds: ['localhost:9300'], + }) + ).toEqual({ + persistent: { + cluster: { + remote: { + test_cluster: { + seeds: ['localhost:9300'], + skip_unavailable: null, + }, + }, + }, + }, + }); + }); + }); +}); diff --git a/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.ts b/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.ts new file mode 100644 index 0000000000000..07ea79d42b800 --- /dev/null +++ b/x-pack/plugins/remote_clusters/common/lib/cluster_serialization.ts @@ -0,0 +1,71 @@ +/* + * 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 function deserializeCluster(name: string, esClusterObject: any): any { + if (!name || !esClusterObject || typeof esClusterObject !== 'object') { + throw new Error('Unable to deserialize cluster'); + } + + const { + seeds, + connected: isConnected, + num_nodes_connected: connectedNodesCount, + max_connections_per_cluster: maxConnectionsPerCluster, + initial_connect_timeout: initialConnectTimeout, + skip_unavailable: skipUnavailable, + transport, + } = esClusterObject; + + let deserializedClusterObject: any = { + name, + seeds, + isConnected, + connectedNodesCount, + maxConnectionsPerCluster, + initialConnectTimeout, + skipUnavailable, + }; + + if (transport) { + const { ping_schedule: transportPingSchedule, compress: transportCompress } = transport; + + deserializedClusterObject = { + ...deserializedClusterObject, + transportPingSchedule, + transportCompress, + }; + } + + // It's unnecessary to send undefined values back to the client, so we can remove them. + Object.keys(deserializedClusterObject).forEach(key => { + if (deserializedClusterObject[key] === undefined) { + delete deserializedClusterObject[key]; + } + }); + + return deserializedClusterObject; +} + +export function serializeCluster(deserializedClusterObject: any): any { + if (!deserializedClusterObject || typeof deserializedClusterObject !== 'object') { + throw new Error('Unable to serialize cluster'); + } + + const { name, seeds, skipUnavailable } = deserializedClusterObject; + + return { + persistent: { + cluster: { + remote: { + [name]: { + seeds: seeds ? seeds : null, + skip_unavailable: skipUnavailable !== undefined ? skipUnavailable : null, + }, + }, + }, + }, + }; +} diff --git a/x-pack/legacy/plugins/remote_clusters/server/index.ts b/x-pack/plugins/remote_clusters/common/lib/index.ts similarity index 67% rename from x-pack/legacy/plugins/remote_clusters/server/index.ts rename to x-pack/plugins/remote_clusters/common/lib/index.ts index 0c6380a279d24..bc67bf21af038 100644 --- a/x-pack/legacy/plugins/remote_clusters/server/index.ts +++ b/x-pack/plugins/remote_clusters/common/lib/index.ts @@ -3,6 +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. */ -import { RemoteClustersServerPlugin } from './plugin'; -export const plugin = () => new RemoteClustersServerPlugin(); +export { deserializeCluster, serializeCluster } from './cluster_serialization'; diff --git a/x-pack/legacy/plugins/remote_clusters/kibana.json b/x-pack/plugins/remote_clusters/kibana.json similarity index 76% rename from x-pack/legacy/plugins/remote_clusters/kibana.json rename to x-pack/plugins/remote_clusters/kibana.json index 0934c94cfc3fe..de1e3d1e26865 100644 --- a/x-pack/legacy/plugins/remote_clusters/kibana.json +++ b/x-pack/plugins/remote_clusters/kibana.json @@ -2,8 +2,8 @@ "id": "remote_clusters", "version": "kibana", "requiredPlugins": [ - "home" + "licensing" ], "server": true, - "ui": true + "ui": false } diff --git a/x-pack/plugins/remote_clusters/server/index.ts b/x-pack/plugins/remote_clusters/server/index.ts new file mode 100644 index 0000000000000..896161d82919b --- /dev/null +++ b/x-pack/plugins/remote_clusters/server/index.ts @@ -0,0 +1,9 @@ +/* + * 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 { PluginInitializerContext } from 'kibana/server'; +import { RemoteClustersServerPlugin } from './plugin'; + +export const plugin = (ctx: PluginInitializerContext) => new RemoteClustersServerPlugin(ctx); diff --git a/x-pack/legacy/plugins/remote_clusters/server/lib/call_with_request_factory/call_with_request_factory.ts b/x-pack/plugins/remote_clusters/server/lib/call_with_request_factory/call_with_request_factory.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/server/lib/call_with_request_factory/call_with_request_factory.ts rename to x-pack/plugins/remote_clusters/server/lib/call_with_request_factory/call_with_request_factory.ts diff --git a/x-pack/legacy/plugins/remote_clusters/server/lib/call_with_request_factory/index.ts b/x-pack/plugins/remote_clusters/server/lib/call_with_request_factory/index.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/server/lib/call_with_request_factory/index.ts rename to x-pack/plugins/remote_clusters/server/lib/call_with_request_factory/index.ts diff --git a/x-pack/legacy/plugins/remote_clusters/server/lib/does_cluster_exist.ts b/x-pack/plugins/remote_clusters/server/lib/does_cluster_exist.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/server/lib/does_cluster_exist.ts rename to x-pack/plugins/remote_clusters/server/lib/does_cluster_exist.ts diff --git a/x-pack/legacy/plugins/remote_clusters/server/lib/is_es_error/index.ts b/x-pack/plugins/remote_clusters/server/lib/is_es_error/index.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/server/lib/is_es_error/index.ts rename to x-pack/plugins/remote_clusters/server/lib/is_es_error/index.ts diff --git a/x-pack/legacy/plugins/remote_clusters/server/lib/is_es_error/is_es_error.ts b/x-pack/plugins/remote_clusters/server/lib/is_es_error/is_es_error.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/server/lib/is_es_error/is_es_error.ts rename to x-pack/plugins/remote_clusters/server/lib/is_es_error/is_es_error.ts diff --git a/x-pack/legacy/plugins/remote_clusters/server/lib/license_pre_routing_factory/index.ts b/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/index.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/server/lib/license_pre_routing_factory/index.ts rename to x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/index.ts diff --git a/x-pack/legacy/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.test.js b/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.test.ts similarity index 53% rename from x-pack/legacy/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.test.js rename to x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.test.ts index b6cea09e0ea3c..dcb6cc536ba7a 100644 --- a/x-pack/legacy/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.test.js +++ b/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.test.ts @@ -5,40 +5,21 @@ */ import expect from '@kbn/expect'; -import { licensePreRoutingFactory } from '.'; -import { - LICENSE_STATUS_VALID, - LICENSE_STATUS_INVALID, -} from '../../../../../common/constants/license_status'; -import { kibanaResponseFactory } from '../../../../../../../src/core/server'; +import { kibanaResponseFactory } from '../../../../../../src/core/server'; +import { licensePreRoutingFactory } from '../license_pre_routing_factory'; describe('licensePreRoutingFactory()', () => { - let mockServer; - let mockLicenseCheckResults; + let mockDeps; + let licenseStatus; beforeEach(() => { - mockServer = { - plugins: { - xpack_main: { - info: { - feature: () => ({ - getLicenseCheckResults: () => mockLicenseCheckResults, - }), - }, - }, - }, - }; + mockDeps = { getLicenseStatus: () => licenseStatus }; }); - describe('status is invalid', () => { - beforeEach(() => { - mockLicenseCheckResults = { - status: LICENSE_STATUS_INVALID, - }; - }); - + describe('status is not valid', () => { it('replies with 403', () => { - const routeWithLicenseCheck = licensePreRoutingFactory(mockServer, () => {}); + licenseStatus = { valid: false }; + const routeWithLicenseCheck = licensePreRoutingFactory(mockDeps, () => {}); const stubRequest = {}; const response = routeWithLicenseCheck({}, stubRequest, kibanaResponseFactory); expect(response.status).to.be(403); @@ -46,14 +27,9 @@ describe('licensePreRoutingFactory()', () => { }); describe('status is valid', () => { - beforeEach(() => { - mockLicenseCheckResults = { - status: LICENSE_STATUS_VALID, - }; - }); - it('replies with nothing', () => { - const routeWithLicenseCheck = licensePreRoutingFactory(mockServer, () => null); + licenseStatus = { valid: true }; + const routeWithLicenseCheck = licensePreRoutingFactory(mockDeps, () => null); const stubRequest = {}; const response = routeWithLicenseCheck({}, stubRequest, kibanaResponseFactory); expect(response).to.be(null); diff --git a/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts b/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts new file mode 100644 index 0000000000000..481de968e661c --- /dev/null +++ b/x-pack/plugins/remote_clusters/server/lib/license_pre_routing_factory/license_pre_routing_factory.ts @@ -0,0 +1,35 @@ +/* + * 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 { + KibanaRequest, + KibanaResponseFactory, + RequestHandler, + RequestHandlerContext, +} from 'kibana/server'; +import { RouteDependencies } from '../../types'; + +export const licensePreRoutingFactory = ( + { getLicenseStatus }: RouteDependencies, + handler: RequestHandler +) => { + return function licenseCheck( + ctx: RequestHandlerContext, + request: KibanaRequest, + response: KibanaResponseFactory + ) { + const licenseStatus = getLicenseStatus(); + if (!licenseStatus.valid) { + return response.forbidden({ + body: { + message: licenseStatus.message || '', + }, + }); + } + + return handler(ctx, request, response); + }; +}; diff --git a/x-pack/plugins/remote_clusters/server/plugin.ts b/x-pack/plugins/remote_clusters/server/plugin.ts new file mode 100644 index 0000000000000..dd0bb536d2695 --- /dev/null +++ b/x-pack/plugins/remote_clusters/server/plugin.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 { i18n } from '@kbn/i18n'; + +import { CoreSetup, Logger, Plugin, PluginInitializerContext } from 'src/core/server'; +import { PLUGIN } from '../common/constants'; +import { LICENSE_CHECK_STATE } from '../../licensing/common/types'; +import { Dependencies, LicenseStatus, RouteDependencies } from './types'; + +import { + registerGetRoute, + registerAddRoute, + registerUpdateRoute, + registerDeleteRoute, +} from './routes/api'; + +export class RemoteClustersServerPlugin implements Plugin { + licenseStatus: LicenseStatus; + log: Logger; + + constructor({ logger }: PluginInitializerContext) { + this.log = logger.get(); + this.licenseStatus = { valid: false }; + } + + async setup( + { http, elasticsearch: elasticsearchService }: CoreSetup, + { licensing }: Dependencies + ) { + const elasticsearch = await elasticsearchService.adminClient; + const router = http.createRouter(); + const routeDependencies: RouteDependencies = { + elasticsearch, + elasticsearchService, + router, + getLicenseStatus: () => this.licenseStatus, + }; + + // Register routes + registerGetRoute(routeDependencies); + registerAddRoute(routeDependencies); + registerUpdateRoute(routeDependencies); + registerDeleteRoute(routeDependencies); + + licensing.license$.subscribe(license => { + const { state, message } = license.check(PLUGIN.id, PLUGIN.minimumLicenseType); + const hasRequiredLicense = state === LICENSE_CHECK_STATE.Valid; + if (hasRequiredLicense) { + this.licenseStatus = { valid: true }; + } else { + this.licenseStatus = { + valid: false, + message: + message || + i18n.translate('xpack.remoteClusters.licenseCheckErrorMessage', { + defaultMessage: 'License check failed', + }), + }; + if (message) { + this.log.info(message); + } + } + }); + } + + start() {} + + stop() {} +} diff --git a/x-pack/legacy/plugins/remote_clusters/server/routes/api/add_route.test.ts b/x-pack/plugins/remote_clusters/server/routes/api/add_route.test.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/server/routes/api/add_route.test.ts rename to x-pack/plugins/remote_clusters/server/routes/api/add_route.test.ts diff --git a/x-pack/legacy/plugins/remote_clusters/server/routes/api/add_route.ts b/x-pack/plugins/remote_clusters/server/routes/api/add_route.ts similarity index 87% rename from x-pack/legacy/plugins/remote_clusters/server/routes/api/add_route.ts rename to x-pack/plugins/remote_clusters/server/routes/api/add_route.ts index 71791385f63ab..714653e27b079 100644 --- a/x-pack/legacy/plugins/remote_clusters/server/routes/api/add_route.ts +++ b/x-pack/plugins/remote_clusters/server/routes/api/add_route.ts @@ -9,16 +9,16 @@ import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; import { RequestHandler } from 'src/core/server'; -import { serializeCluster } from '../../../common/cluster_serialization'; +import { serializeCluster } from '../../../common/lib'; import { doesClusterExist } from '../../lib/does_cluster_exist'; -import { API_BASE_PATH } from '../../../common'; +import { API_BASE_PATH } from '../../../common/constants'; import { licensePreRoutingFactory } from '../../lib/license_pre_routing_factory'; import { callWithRequestFactory } from '../../lib/call_with_request_factory'; import { isEsError } from '../../lib/is_es_error'; -import { RouteDependencies, ServerShim } from '../../types'; +import { RouteDependencies } from '../../types'; -export const register = (deps: RouteDependencies, legacy: ServerShim): void => { - const getAddHandler: RequestHandler = async (ctx, request, response) => { +export const register = (deps: RouteDependencies): void => { + const addHandler: RequestHandler = async (ctx, request, response) => { try { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); @@ -86,6 +86,6 @@ export const register = (deps: RouteDependencies, legacy: ServerShim): void => { }), }, }, - licensePreRoutingFactory(legacy, getAddHandler) + licensePreRoutingFactory(deps, addHandler) ); }; diff --git a/x-pack/legacy/plugins/remote_clusters/server/routes/api/delete_route.test.ts b/x-pack/plugins/remote_clusters/server/routes/api/delete_route.test.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/server/routes/api/delete_route.test.ts rename to x-pack/plugins/remote_clusters/server/routes/api/delete_route.test.ts diff --git a/x-pack/legacy/plugins/remote_clusters/server/routes/api/delete_route.ts b/x-pack/plugins/remote_clusters/server/routes/api/delete_route.ts similarity index 90% rename from x-pack/legacy/plugins/remote_clusters/server/routes/api/delete_route.ts rename to x-pack/plugins/remote_clusters/server/routes/api/delete_route.ts index d11cc79ecbfee..cfffa7621006a 100644 --- a/x-pack/legacy/plugins/remote_clusters/server/routes/api/delete_route.ts +++ b/x-pack/plugins/remote_clusters/server/routes/api/delete_route.ts @@ -9,16 +9,16 @@ import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; import { RequestHandler } from 'src/core/server'; -import { RouteDependencies, ServerShim } from '../../types'; -import { serializeCluster } from '../../../common/cluster_serialization'; -import { API_BASE_PATH } from '../../../common'; +import { RouteDependencies } from '../../types'; +import { serializeCluster } from '../../../common/lib'; +import { API_BASE_PATH } from '../../../common/constants'; import { doesClusterExist } from '../../lib/does_cluster_exist'; import { licensePreRoutingFactory } from '../../lib/license_pre_routing_factory'; import { isEsError } from '../../lib/is_es_error'; import { callWithRequestFactory } from '../../lib/call_with_request_factory'; -export const register = (deps: RouteDependencies, legacy: ServerShim): void => { - const getDeleteHandler: RequestHandler = async (ctx, request, response) => { +export const register = (deps: RouteDependencies): void => { + const deleteHandler: RequestHandler = async (ctx, request, response) => { try { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); @@ -125,6 +125,6 @@ export const register = (deps: RouteDependencies, legacy: ServerShim): void => { }), }, }, - licensePreRoutingFactory(legacy, getDeleteHandler) + licensePreRoutingFactory(deps, deleteHandler) ); }; diff --git a/x-pack/legacy/plugins/remote_clusters/server/routes/api/get_route.test.ts b/x-pack/plugins/remote_clusters/server/routes/api/get_route.test.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/server/routes/api/get_route.test.ts rename to x-pack/plugins/remote_clusters/server/routes/api/get_route.test.ts diff --git a/x-pack/legacy/plugins/remote_clusters/server/routes/api/get_route.ts b/x-pack/plugins/remote_clusters/server/routes/api/get_route.ts similarity index 83% rename from x-pack/legacy/plugins/remote_clusters/server/routes/api/get_route.ts rename to x-pack/plugins/remote_clusters/server/routes/api/get_route.ts index a5f80d5c844a9..b205b3424c04b 100644 --- a/x-pack/legacy/plugins/remote_clusters/server/routes/api/get_route.ts +++ b/x-pack/plugins/remote_clusters/server/routes/api/get_route.ts @@ -7,15 +7,15 @@ import { get } from 'lodash'; import { RequestHandler } from 'src/core/server'; -import { deserializeCluster } from '../../../common/cluster_serialization'; -import { API_BASE_PATH } from '../../../common'; +import { deserializeCluster } from '../../../common/lib'; +import { API_BASE_PATH } from '../../../common/constants'; import { licensePreRoutingFactory } from '../../lib/license_pre_routing_factory'; import { callWithRequestFactory } from '../../lib/call_with_request_factory'; import { isEsError } from '../../lib/is_es_error'; -import { RouteDependencies, ServerShim } from '../../types'; +import { RouteDependencies } from '../../types'; -export const register = (deps: RouteDependencies, legacy: ServerShim): void => { - const getAllHandler: RequestHandler = async (ctx, request, response) => { +export const register = (deps: RouteDependencies): void => { + const allHandler: RequestHandler = async (ctx, request, response) => { try { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); const clusterSettings = await callWithRequest('cluster.getSettings'); @@ -58,6 +58,6 @@ export const register = (deps: RouteDependencies, legacy: ServerShim): void => { path: API_BASE_PATH, validate: false, }, - licensePreRoutingFactory(legacy, getAllHandler) + licensePreRoutingFactory(deps, allHandler) ); }; diff --git a/x-pack/legacy/plugins/remote_clusters/server/routes/api/index.ts b/x-pack/plugins/remote_clusters/server/routes/api/index.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/server/routes/api/index.ts rename to x-pack/plugins/remote_clusters/server/routes/api/index.ts diff --git a/x-pack/legacy/plugins/remote_clusters/server/routes/api/update_route.test.ts b/x-pack/plugins/remote_clusters/server/routes/api/update_route.test.ts similarity index 100% rename from x-pack/legacy/plugins/remote_clusters/server/routes/api/update_route.test.ts rename to x-pack/plugins/remote_clusters/server/routes/api/update_route.test.ts diff --git a/x-pack/legacy/plugins/remote_clusters/server/routes/api/update_route.ts b/x-pack/plugins/remote_clusters/server/routes/api/update_route.ts similarity index 90% rename from x-pack/legacy/plugins/remote_clusters/server/routes/api/update_route.ts rename to x-pack/plugins/remote_clusters/server/routes/api/update_route.ts index 661c17fc06f12..2d6e7ad89cb6e 100644 --- a/x-pack/legacy/plugins/remote_clusters/server/routes/api/update_route.ts +++ b/x-pack/plugins/remote_clusters/server/routes/api/update_route.ts @@ -9,17 +9,17 @@ import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; import { RequestHandler } from 'src/core/server'; -import { API_BASE_PATH } from '../../../common'; -import { serializeCluster, deserializeCluster } from '../../../common/cluster_serialization'; +import { API_BASE_PATH } from '../../../common/constants'; +import { serializeCluster, deserializeCluster } from '../../../common/lib'; import { doesClusterExist } from '../../lib/does_cluster_exist'; -import { RouteDependencies, ServerShim } from '../../types'; +import { RouteDependencies } from '../../types'; import { licensePreRoutingFactory } from '../../lib/license_pre_routing_factory'; import { isEsError } from '../../lib/is_es_error'; import { callWithRequestFactory } from '../../lib/call_with_request_factory'; -export const register = (deps: RouteDependencies, legacy: ServerShim): void => { +export const register = (deps: RouteDependencies): void => { // TODO there are other settings that can be specified for a remote cluster via console/API that I think might cause issues when editing - const getUpdateHandler: RequestHandler = async (ctx, request, response) => { + const updateHandler: RequestHandler = async (ctx, request, response) => { try { const callWithRequest = callWithRequestFactory(deps.elasticsearchService, request); @@ -99,6 +99,6 @@ export const register = (deps: RouteDependencies, legacy: ServerShim): void => { }), }, }, - licensePreRoutingFactory(legacy, getUpdateHandler) + licensePreRoutingFactory(deps, updateHandler) ); }; diff --git a/x-pack/legacy/plugins/remote_clusters/server/types.ts b/x-pack/plugins/remote_clusters/server/types.ts similarity index 63% rename from x-pack/legacy/plugins/remote_clusters/server/types.ts rename to x-pack/plugins/remote_clusters/server/types.ts index 99534efefcbef..708b1daf4bbad 100644 --- a/x-pack/legacy/plugins/remote_clusters/server/types.ts +++ b/x-pack/plugins/remote_clusters/server/types.ts @@ -4,19 +4,21 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IRouter, ElasticsearchServiceSetup, IClusterClient } from 'src/core/server'; -import { XPackMainPlugin } from '../../xpack_main/server/xpack_main'; +import { IRouter, ElasticsearchServiceSetup, IClusterClient } from 'kibana/server'; +import { LicensingPluginSetup } from '../../licensing/server'; -export interface ServerShim { - route: any; - plugins: { - xpack_main: XPackMainPlugin; - remote_clusters: any; - }; +export interface Dependencies { + licensing: LicensingPluginSetup; } export interface RouteDependencies { router: IRouter; + getLicenseStatus: () => LicenseStatus; elasticsearchService: ElasticsearchServiceSetup; elasticsearch: IClusterClient; } + +export interface LicenseStatus { + valid: boolean; + message?: string; +}