does not play well with the angular router. It will cause this controller
- // to re-execute without the $destroy handler being called. This means that the app will be mounted twice
- // creating a memory leak when leaving (only 1 app will be unmounted).
- // To avoid this, we unmount the React app each time we enter the controller.
- unmountReactApp();
-
- $scope.$$postDigest(() => {
- elem = document.getElementById(CCR_REACT_ROOT);
- renderReact(elem, npStart.core.i18n.Context);
-
- // Angular Lifecycle
- const appRoute = $route.current;
- const stopListeningForLocationChange = $scope.$on('$locationChangeSuccess', () => {
- const currentRoute = $route.current;
- const isNavigationInApp = currentRoute.$$route.template === appRoute.$$route.template;
-
- // When we navigate within CCR, prevent Angular from re-matching the route and rebuild the app
- if (isNavigationInApp) {
- $route.current = appRoute;
- } else {
- // Any clean up when User leaves the CCR
- }
-
- $scope.$on('$destroy', () => {
- stopListeningForLocationChange && stopListeningForLocationChange();
- unmountReactApp();
- });
- });
- });
- }
- },
- });
-}
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/cross_cluster_replication_data.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/cross_cluster_replication_data.ts
deleted file mode 100644
index ae15073b979e1..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/cross_cluster_replication_data.ts
+++ /dev/null
@@ -1,36 +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 { APICaller } from 'src/core/server';
-import { Index } from '../../../../../plugins/index_management/server';
-
-export const ccrDataEnricher = async (indicesList: Index[], callWithRequest: APICaller) => {
- if (!indicesList?.length) {
- return indicesList;
- }
- const params = {
- path: '/_all/_ccr/info',
- method: 'GET',
- };
- try {
- const { follower_indices: followerIndices } = await callWithRequest(
- 'transport.request',
- params
- );
- return indicesList.map(index => {
- const isFollowerIndex = !!followerIndices.find(
- (followerIndex: { follower_index: string }) => {
- return followerIndex.follower_index === index.name;
- }
- );
- return {
- ...index,
- isFollowerIndex,
- };
- });
- } catch (e) {
- return indicesList;
- }
-};
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/index.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/index.ts
deleted file mode 100644
index 7a38d024d99a2..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/index.ts
+++ /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 { PluginInitializerContext } from 'src/core/server';
-import { CrossClusterReplicationServerPlugin } from './plugin';
-
-export const plugin = (ctx: PluginInitializerContext) =>
- new CrossClusterReplicationServerPlugin(ctx);
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/call_with_request_factory/call_with_request_factory.js b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/call_with_request_factory/call_with_request_factory.js
deleted file mode 100644
index 99d72ce1a0e6e..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/call_with_request_factory/call_with_request_factory.js
+++ /dev/null
@@ -1,20 +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 { elasticsearchJsPlugin } from '../../client/elasticsearch_ccr';
-
-const callWithRequest = once(server => {
- const config = { plugins: [elasticsearchJsPlugin] };
- const cluster = server.plugins.elasticsearch.createCluster('ccr', config);
- return cluster.callWithRequest;
-});
-
-export const callWithRequestFactory = (server, request) => {
- return (...args) => {
- return callWithRequest(server)(request, ...args);
- };
-};
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/call_with_request_factory/index.js b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/call_with_request_factory/index.js
deleted file mode 100644
index 787814d87dff9..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/call_with_request_factory/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 { callWithRequestFactory } from './call_with_request_factory';
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/check_license/check_license.js b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/check_license/check_license.js
deleted file mode 100644
index 6cf12896fa472..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/check_license/check_license.js
+++ /dev/null
@@ -1,70 +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 { i18n } from '@kbn/i18n';
-
-export function checkLicense(xpackLicenseInfo) {
- const pluginName = 'Cross-Cluster Replication';
-
- // If, for some reason, we cannot get the license information
- // from Elasticsearch, assume worst case and disable
- if (!xpackLicenseInfo || !xpackLicenseInfo.isAvailable()) {
- return {
- isAvailable: false,
- showLinks: true,
- enableLinks: false,
- message: i18n.translate(
- 'xpack.crossClusterReplication.checkLicense.errorUnavailableMessage',
- {
- defaultMessage:
- 'You cannot use {pluginName} because license information is not available at this time.',
- values: { pluginName },
- }
- ),
- };
- }
-
- const VALID_LICENSE_MODES = ['trial', 'platinum', 'enterprise'];
-
- const isLicenseModeValid = xpackLicenseInfo.license.isOneOf(VALID_LICENSE_MODES);
- const isLicenseActive = xpackLicenseInfo.license.isActive();
- const licenseType = xpackLicenseInfo.license.getType();
-
- // License is not valid
- if (!isLicenseModeValid) {
- return {
- isAvailable: false,
- isActive: false,
- message: i18n.translate(
- 'xpack.crossClusterReplication.checkLicense.errorUnsupportedMessage',
- {
- defaultMessage:
- 'Your {licenseType} license does not support {pluginName}. Please upgrade your license.',
- values: { licenseType, pluginName },
- }
- ),
- };
- }
-
- // License is valid but not active
- if (!isLicenseActive) {
- return {
- isAvailable: true,
- isActive: false,
- message: i18n.translate('xpack.crossClusterReplication.checkLicense.errorExpiredMessage', {
- defaultMessage:
- 'You cannot use {pluginName} because your {licenseType} license has expired',
- values: { licenseType, pluginName },
- }),
- };
- }
-
- // License is valid and active
- return {
- isAvailable: true,
- isActive: true,
- };
-}
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/error_wrappers/__tests__/wrap_es_error.test.js b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/error_wrappers/__tests__/wrap_es_error.test.js
deleted file mode 100644
index 11a6fd4e1d816..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/error_wrappers/__tests__/wrap_es_error.test.js
+++ /dev/null
@@ -1,33 +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;
- originalError.response = '{}';
- });
-
- it('should return the correct object', () => {
- const wrappedError = wrapEsError(originalError);
-
- expect(wrappedError.statusCode).to.be(originalError.statusCode);
- expect(wrappedError.message).to.be(originalError.message);
- });
-
- it('should return the correct object with custom message', () => {
- const wrappedError = wrapEsError(originalError, { 404: 'No encontrado!' });
-
- expect(wrappedError.statusCode).to.be(originalError.statusCode);
- expect(wrappedError.message).to.be('No encontrado!');
- });
- });
-});
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/is_es_error_factory/__tests__/is_es_error_factory.js b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/is_es_error_factory/__tests__/is_es_error_factory.js
deleted file mode 100644
index 5f2141cce9395..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/is_es_error_factory/__tests__/is_es_error_factory.js
+++ /dev/null
@@ -1,44 +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 { isEsErrorFactory } from '../is_es_error_factory';
-import { set } from 'lodash';
-
-class MockAbstractEsError {}
-
-describe('is_es_error_factory', () => {
- let mockServer;
- let isEsError;
-
- beforeEach(() => {
- const mockEsErrors = {
- _Abstract: MockAbstractEsError,
- };
- mockServer = {};
- set(mockServer, 'plugins.elasticsearch.getCluster', () => ({ errors: mockEsErrors }));
-
- isEsError = isEsErrorFactory(mockServer);
- });
-
- describe('#isEsErrorFactory', () => {
- it('should return a function', () => {
- expect(isEsError).to.be.a(Function);
- });
-
- describe('returned function', () => {
- it('should return true if passed-in err is a known esError', () => {
- const knownEsError = new MockAbstractEsError();
- expect(isEsError(knownEsError)).to.be(true);
- });
-
- it('should return false if passed-in err is not a known esError', () => {
- const unknownEsError = {};
- expect(isEsError(unknownEsError)).to.be(false);
- });
- });
- });
-});
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/is_es_error_factory/is_es_error_factory.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/is_es_error_factory/is_es_error_factory.ts
deleted file mode 100644
index fc6405b8e7513..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/is_es_error_factory/is_es_error_factory.ts
+++ /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 { memoize } from 'lodash';
-
-const esErrorsFactory = memoize((server: any) => {
- return server.plugins.elasticsearch.getCluster('admin').errors;
-});
-
-export function isEsErrorFactory(server: any) {
- const esErrors = esErrorsFactory(server);
- return function isEsError(err: any) {
- return err instanceof esErrors._Abstract;
- };
-}
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/license_pre_routing_factory/__jest__/license_pre_routing_factory.test.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/license_pre_routing_factory/__jest__/license_pre_routing_factory.test.ts
deleted file mode 100644
index d22505f0e315a..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/license_pre_routing_factory/__jest__/license_pre_routing_factory.test.ts
+++ /dev/null
@@ -1,64 +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 { kibanaResponseFactory } from '../../../../../../../../../src/core/server';
-import { licensePreRoutingFactory } from '../license_pre_routing_factory';
-
-describe('license_pre_routing_factory', () => {
- describe('#reportingFeaturePreRoutingFactory', () => {
- let mockDeps: any;
- let mockLicenseCheckResults: any;
-
- const anyContext: any = {};
- const anyRequest: any = {};
-
- beforeEach(() => {
- mockDeps = {
- __LEGACY: {
- server: {
- plugins: {
- xpack_main: {
- info: {
- feature: () => ({
- getLicenseCheckResults: () => mockLicenseCheckResults,
- }),
- },
- },
- },
- },
- },
- requestHandler: jest.fn(),
- };
- });
-
- describe('isAvailable is false', () => {
- beforeEach(() => {
- mockLicenseCheckResults = {
- isAvailable: false,
- };
- });
-
- it('replies with 403', async () => {
- const licensePreRouting = licensePreRoutingFactory(mockDeps);
- const response = await licensePreRouting(anyContext, anyRequest, kibanaResponseFactory);
- expect(response.status).toBe(403);
- });
- });
-
- describe('isAvailable is true', () => {
- beforeEach(() => {
- mockLicenseCheckResults = {
- isAvailable: true,
- };
- });
-
- it('it calls the wrapped handler', async () => {
- const licensePreRouting = licensePreRoutingFactory(mockDeps);
- await licensePreRouting(anyContext, anyRequest, kibanaResponseFactory);
- expect(mockDeps.requestHandler).toHaveBeenCalledTimes(1);
- });
- });
- });
-});
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/license_pre_routing_factory/license_pre_routing_factory.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/license_pre_routing_factory/license_pre_routing_factory.ts
deleted file mode 100644
index c47faa940a650..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/license_pre_routing_factory/license_pre_routing_factory.ts
+++ /dev/null
@@ -1,32 +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 { RequestHandler } from 'src/core/server';
-import { PLUGIN } from '../../../../common/constants';
-
-export const licensePreRoutingFactory = ({
- __LEGACY,
- requestHandler,
-}: {
- __LEGACY: { server: any };
- requestHandler: RequestHandler
;
-}) => {
- const xpackMainPlugin = __LEGACY.server.plugins.xpack_main;
-
- // License checking and enable/disable logic
- const licensePreRouting: RequestHandler
= (ctx, request, response) => {
- const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults();
- if (!licenseCheckResults.isAvailable) {
- return response.forbidden({
- body: licenseCheckResults.message,
- });
- } else {
- return requestHandler(ctx, request, response);
- }
- };
-
- return licensePreRouting;
-};
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/register_license_checker/index.js b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/register_license_checker/index.js
deleted file mode 100644
index 7b0f97c38d129..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/register_license_checker/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 { registerLicenseChecker } from './register_license_checker';
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/register_license_checker/register_license_checker.js b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/register_license_checker/register_license_checker.js
deleted file mode 100644
index b9bb34a80ce79..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/lib/register_license_checker/register_license_checker.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 { mirrorPluginStatus } from '../../../../../../server/lib/mirror_plugin_status';
-import { PLUGIN } from '../../../../common/constants';
-import { checkLicense } from '../check_license';
-
-export function registerLicenseChecker(__LEGACY) {
- const xpackMainPlugin = __LEGACY.server.plugins.xpack_main;
- const ccrPluggin = __LEGACY.server.plugins[PLUGIN.ID];
-
- mirrorPluginStatus(xpackMainPlugin, ccrPluggin);
- xpackMainPlugin.status.once('green', () => {
- // Register a function that is called whenever the xpack info changes,
- // to re-compute the license check results for this plugin
- xpackMainPlugin.info.feature(PLUGIN.ID).registerLicenseCheckResultsGenerator(checkLicense);
- });
-}
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/plugin.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/plugin.ts
deleted file mode 100644
index 829de10ad0177..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/plugin.ts
+++ /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 { Plugin, PluginInitializerContext, CoreSetup } from 'src/core/server';
-
-import { IndexManagementPluginSetup } from '../../../../../plugins/index_management/server';
-
-// @ts-ignore
-import { registerLicenseChecker } from './lib/register_license_checker';
-// @ts-ignore
-import { registerRoutes } from './routes/register_routes';
-import { ccrDataEnricher } from './cross_cluster_replication_data';
-
-interface PluginDependencies {
- indexManagement: IndexManagementPluginSetup;
- __LEGACY: {
- server: any;
- ccrUIEnabled: boolean;
- };
-}
-
-export class CrossClusterReplicationServerPlugin implements Plugin {
- // @ts-ignore
- constructor(private readonly ctx: PluginInitializerContext) {}
- setup({ http }: CoreSetup, { indexManagement, __LEGACY }: PluginDependencies) {
- registerLicenseChecker(__LEGACY);
-
- const router = http.createRouter();
- registerRoutes({ router, __LEGACY });
- if (__LEGACY.ccrUIEnabled && indexManagement && indexManagement.indexDataEnricher) {
- indexManagement.indexDataEnricher.add(ccrDataEnricher);
- }
- }
- start() {}
-}
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/__jest__/auto_follow_pattern.test.js b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/__jest__/auto_follow_pattern.test.js
deleted file mode 100644
index f3024515c7213..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/__jest__/auto_follow_pattern.test.js
+++ /dev/null
@@ -1,330 +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 { deserializeAutoFollowPattern } from '../../../../../common/services/auto_follow_pattern_serialization';
-import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
-import { isEsErrorFactory } from '../../../lib/is_es_error_factory';
-import { getAutoFollowPatternMock, getAutoFollowPatternListMock } from '../../../../../fixtures';
-import { registerAutoFollowPatternRoutes } from '../auto_follow_pattern';
-
-import { createRouter, callRoute } from './helpers';
-
-jest.mock('../../../lib/call_with_request_factory');
-jest.mock('../../../lib/is_es_error_factory');
-jest.mock('../../../lib/license_pre_routing_factory', () => ({
- licensePreRoutingFactory: ({ requestHandler }) => requestHandler,
-}));
-
-const DESERIALIZED_KEYS = Object.keys(deserializeAutoFollowPattern(getAutoFollowPatternMock()));
-
-let routeRegistry;
-
-/**
- * Helper to extract all the different server route handler so we can easily call them in our tests.
- *
- * Important: This method registers the handlers in the order that they appear in the file, so
- * if a "server.route()" call is moved or deleted, then the HANDLER_INDEX_TO_ACTION must be updated here.
- */
-const registerHandlers = () => {
- const HANDLER_INDEX_TO_ACTION = {
- 0: 'list',
- 1: 'create',
- 2: 'update',
- 3: 'get',
- 4: 'delete',
- 5: 'pause',
- 6: 'resume',
- };
-
- routeRegistry = createRouter(HANDLER_INDEX_TO_ACTION);
-
- registerAutoFollowPatternRoutes({
- __LEGACY: {},
- router: routeRegistry.router,
- });
-};
-
-/**
- * Queue to save request response and errors
- * It allows us to fake multiple responses from the
- * callWithRequestFactory() when the request handler call it
- * multiple times.
- */
-let requestResponseQueue = [];
-
-/**
- * Helper to mock the response from the call to Elasticsearch
- *
- * @param {*} err The mock error to throw
- * @param {*} response The response to return
- */
-const setHttpRequestResponse = (error, response) => {
- requestResponseQueue.push({ error, response });
-};
-
-const resetHttpRequestResponses = () => (requestResponseQueue = []);
-
-const getNextResponseFromQueue = () => {
- if (!requestResponseQueue.length) {
- return null;
- }
-
- const next = requestResponseQueue.shift();
- if (next.error) {
- return Promise.reject(next.error);
- }
- return Promise.resolve(next.response);
-};
-
-describe('[CCR API Routes] Auto Follow Pattern', () => {
- let routeHandler;
-
- beforeAll(() => {
- isEsErrorFactory.mockReturnValue(() => false);
- callWithRequestFactory.mockReturnValue(getNextResponseFromQueue);
- registerHandlers();
- });
-
- describe('list()', () => {
- beforeEach(() => {
- routeHandler = routeRegistry.getRoutes().list;
- });
-
- it('should deserialize the response from Elasticsearch', async () => {
- const totalResult = 2;
- setHttpRequestResponse(null, getAutoFollowPatternListMock(totalResult));
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler);
- const autoFollowPattern = response.patterns[0];
-
- expect(response.patterns.length).toEqual(totalResult);
- expect(Object.keys(autoFollowPattern)).toEqual(DESERIALIZED_KEYS);
- });
- });
-
- describe('create()', () => {
- beforeEach(() => {
- resetHttpRequestResponses();
- routeHandler = routeRegistry.getRoutes().create;
- });
-
- it('should throw a 409 conflict error if id already exists', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
-
- const response = await callRoute(
- routeHandler,
- {},
- {
- body: {
- id: 'some-id',
- foo: 'bar',
- },
- }
- );
-
- expect(response.status).toEqual(409);
- });
-
- it('should return 200 status when the id does not exist', async () => {
- const error = new Error('Resource not found.');
- error.statusCode = 404;
- setHttpRequestResponse(error);
- setHttpRequestResponse(null, { acknowledge: true });
-
- const {
- options: { body: response },
- } = await callRoute(
- routeHandler,
- {},
- {
- body: {
- id: 'some-id',
- foo: 'bar',
- },
- }
- );
-
- expect(response).toEqual({ acknowledge: true });
- });
- });
-
- describe('update()', () => {
- beforeEach(() => {
- routeHandler = routeRegistry.getRoutes().update;
- });
-
- it('should serialize the payload before sending it to Elasticsearch', async () => {
- callWithRequestFactory.mockReturnValueOnce((_, payload) => payload);
-
- const request = {
- params: { id: 'foo' },
- body: {
- remoteCluster: 'bar1',
- leaderIndexPatterns: ['bar2'],
- followIndexPattern: 'bar3',
- },
- };
-
- const response = await callRoute(routeHandler, {}, request);
-
- expect(response.options.body).toEqual({
- id: 'foo',
- body: {
- remote_cluster: 'bar1',
- leader_index_patterns: ['bar2'],
- follow_index_pattern: 'bar3',
- },
- });
- });
- });
-
- describe('get()', () => {
- beforeEach(() => {
- routeHandler = routeRegistry.getRoutes().get;
- });
-
- it('should return a single resource even though ES return an array with 1 item', async () => {
- const autoFollowPattern = getAutoFollowPatternMock();
- const esResponse = { patterns: [autoFollowPattern] };
-
- setHttpRequestResponse(null, esResponse);
-
- const response = await callRoute(routeHandler, {}, { params: { id: 1 } });
- expect(Object.keys(response.options.body)).toEqual(DESERIALIZED_KEYS);
- });
- });
-
- describe('delete()', () => {
- beforeEach(() => {
- resetHttpRequestResponses();
- routeHandler = routeRegistry.getRoutes().delete;
- });
-
- it('should delete a single item', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: 'a' } });
-
- expect(response.itemsDeleted).toEqual(['a']);
- expect(response.errors).toEqual([]);
- });
-
- it('should accept a list of ids to delete', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
-
- const response = await callRoute(routeHandler, {}, { params: { id: 'a,b,c' } });
-
- expect(response.options.body.itemsDeleted).toEqual(['a', 'b', 'c']);
- });
-
- it('should catch error and return them in array', async () => {
- const error = new Error('something went wrong');
- error.response = '{ "error": {} }';
-
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(error);
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: 'a,b' } });
-
- expect(response.itemsDeleted).toEqual(['a']);
- expect(response.errors[0].id).toEqual('b');
- });
- });
-
- describe('pause()', () => {
- beforeEach(() => {
- resetHttpRequestResponses();
- routeHandler = routeRegistry.getRoutes().pause;
- });
-
- it('accept a single item', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: 'a' } });
-
- expect(response.itemsPaused).toEqual(['a']);
- expect(response.errors).toEqual([]);
- });
-
- it('should accept a list of items to pause', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
-
- const response = await callRoute(routeHandler, {}, { params: { id: 'a,b,c' } });
-
- expect(response.options.body.itemsPaused).toEqual(['a', 'b', 'c']);
- });
-
- it('should catch error and return them in array', async () => {
- const error = new Error('something went wrong');
- error.response = '{ "error": {} }';
-
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(error);
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: 'a,b' } });
-
- expect(response.itemsPaused).toEqual(['a']);
- expect(response.errors[0].id).toEqual('b');
- });
- });
-
- describe('resume()', () => {
- beforeEach(() => {
- resetHttpRequestResponses();
- routeHandler = routeRegistry.getRoutes().resume;
- });
-
- it('accept a single item', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: 'a' } });
-
- expect(response.itemsResumed).toEqual(['a']);
- expect(response.errors).toEqual([]);
- });
-
- it('should accept a list of items to pause', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
-
- const response = await callRoute(routeHandler, {}, { params: { id: 'a,b,c' } });
-
- expect(response.options.body.itemsResumed).toEqual(['a', 'b', 'c']);
- });
-
- it('should catch error and return them in array', async () => {
- const error = new Error('something went wrong');
- error.response = '{ "error": {} }';
-
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(error);
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: 'a,b' } });
-
- expect(response.itemsResumed).toEqual(['a']);
- expect(response.errors[0].id).toEqual('b');
- });
- });
-});
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/__jest__/follower_index.test.js b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/__jest__/follower_index.test.js
deleted file mode 100644
index f0139e5bd7011..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/__jest__/follower_index.test.js
+++ /dev/null
@@ -1,312 +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 { deserializeFollowerIndex } from '../../../../../common/services/follower_index_serialization';
-import {
- getFollowerIndexStatsMock,
- getFollowerIndexListStatsMock,
- getFollowerIndexInfoMock,
- getFollowerIndexListInfoMock,
-} from '../../../../../fixtures';
-import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
-import { isEsErrorFactory } from '../../../lib/is_es_error_factory';
-import { registerFollowerIndexRoutes } from '../follower_index';
-import { createRouter, callRoute } from './helpers';
-
-jest.mock('../../../lib/call_with_request_factory');
-jest.mock('../../../lib/is_es_error_factory');
-jest.mock('../../../lib/license_pre_routing_factory', () => ({
- licensePreRoutingFactory: ({ requestHandler }) => requestHandler,
-}));
-
-const DESERIALIZED_KEYS = Object.keys(
- deserializeFollowerIndex({
- ...getFollowerIndexInfoMock(),
- ...getFollowerIndexStatsMock(),
- })
-);
-
-let routeRegistry;
-
-/**
- * Helper to extract all the different server route handler so we can easily call them in our tests.
- *
- * Important: This method registers the handlers in the order that they appear in the file, so
- * if a 'server.route()' call is moved or deleted, then the HANDLER_INDEX_TO_ACTION must be updated here.
- */
-const registerHandlers = () => {
- const HANDLER_INDEX_TO_ACTION = {
- 0: 'list',
- 1: 'get',
- 2: 'create',
- 3: 'edit',
- 4: 'pause',
- 5: 'resume',
- 6: 'unfollow',
- };
-
- routeRegistry = createRouter(HANDLER_INDEX_TO_ACTION);
- registerFollowerIndexRoutes({
- __LEGACY: {},
- router: routeRegistry.router,
- });
-};
-
-/**
- * Queue to save request response and errors
- * It allows us to fake multiple responses from the
- * callWithRequestFactory() when the request handler call it
- * multiple times.
- */
-let requestResponseQueue = [];
-
-/**
- * Helper to mock the response from the call to Elasticsearch
- *
- * @param {*} err The mock error to throw
- * @param {*} response The response to return
- */
-const setHttpRequestResponse = (error, response) => {
- requestResponseQueue.push({ error, response });
-};
-
-const resetHttpRequestResponses = () => (requestResponseQueue = []);
-
-const getNextResponseFromQueue = () => {
- if (!requestResponseQueue.length) {
- return null;
- }
-
- const next = requestResponseQueue.shift();
- if (next.error) {
- return Promise.reject(next.error);
- }
- return Promise.resolve(next.response);
-};
-
-describe('[CCR API Routes] Follower Index', () => {
- let routeHandler;
-
- beforeAll(() => {
- isEsErrorFactory.mockReturnValue(() => false);
- callWithRequestFactory.mockReturnValue(getNextResponseFromQueue);
- registerHandlers();
- });
-
- describe('list()', () => {
- beforeEach(() => {
- routeHandler = routeRegistry.getRoutes().list;
- });
-
- it('deserializes the response from Elasticsearch', async () => {
- const totalResult = 2;
- const infoResult = getFollowerIndexListInfoMock(totalResult);
- const statsResult = getFollowerIndexListStatsMock(
- totalResult,
- infoResult.follower_indices.map(index => index.follower_index)
- );
- setHttpRequestResponse(null, infoResult);
- setHttpRequestResponse(null, statsResult);
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler);
- const followerIndex = response.indices[0];
-
- expect(response.indices.length).toEqual(totalResult);
- expect(Object.keys(followerIndex)).toEqual(DESERIALIZED_KEYS);
- });
- });
-
- describe('get()', () => {
- beforeEach(() => {
- routeHandler = routeRegistry.getRoutes().get;
- });
-
- it('should return a single resource even though ES return an array with 1 item', async () => {
- const mockId = 'test1';
- const followerIndexInfo = getFollowerIndexInfoMock(mockId);
- const followerIndexStats = getFollowerIndexStatsMock(mockId);
-
- setHttpRequestResponse(null, { follower_indices: [followerIndexInfo] });
- setHttpRequestResponse(null, { indices: [followerIndexStats] });
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: mockId } });
- expect(Object.keys(response)).toEqual(DESERIALIZED_KEYS);
- });
- });
-
- describe('create()', () => {
- beforeEach(() => {
- resetHttpRequestResponses();
- routeHandler = routeRegistry.getRoutes().create;
- });
-
- it('should return 200 status when follower index is created', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
-
- const response = await callRoute(
- routeHandler,
- {},
- {
- body: {
- name: 'follower_index',
- remoteCluster: 'remote_cluster',
- leaderIndex: 'leader_index',
- },
- }
- );
-
- expect(response.options.body).toEqual({ acknowledge: true });
- });
- });
-
- describe('pause()', () => {
- beforeEach(() => {
- resetHttpRequestResponses();
- routeHandler = routeRegistry.getRoutes().pause;
- });
-
- it('should pause a single item', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: '1' } });
-
- expect(response.itemsPaused).toEqual(['1']);
- expect(response.errors).toEqual([]);
- });
-
- it('should accept a list of ids to pause', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
-
- const response = await callRoute(routeHandler, {}, { params: { id: '1,2,3' } });
-
- expect(response.options.body.itemsPaused).toEqual(['1', '2', '3']);
- });
-
- it('should catch error and return them in array', async () => {
- const error = new Error('something went wrong');
- error.response = '{ "error": {} }';
-
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(error);
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: '1,2' } });
-
- expect(response.itemsPaused).toEqual(['1']);
- expect(response.errors[0].id).toEqual('2');
- });
- });
-
- describe('resume()', () => {
- beforeEach(() => {
- resetHttpRequestResponses();
- routeHandler = routeRegistry.getRoutes().resume;
- });
-
- it('should resume a single item', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: '1' } });
-
- expect(response.itemsResumed).toEqual(['1']);
- expect(response.errors).toEqual([]);
- });
-
- it('should accept a list of ids to resume', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
-
- const response = await callRoute(routeHandler, {}, { params: { id: '1,2,3' } });
-
- expect(response.options.body.itemsResumed).toEqual(['1', '2', '3']);
- });
-
- it('should catch error and return them in array', async () => {
- const error = new Error('something went wrong');
- error.response = '{ "error": {} }';
-
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(error);
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: '1,2' } });
-
- expect(response.itemsResumed).toEqual(['1']);
- expect(response.errors[0].id).toEqual('2');
- });
- });
-
- describe('unfollow()', () => {
- beforeEach(() => {
- resetHttpRequestResponses();
- routeHandler = routeRegistry.getRoutes().unfollow;
- });
-
- it('should unfollow await single item', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: '1' } });
-
- expect(response.itemsUnfollowed).toEqual(['1']);
- expect(response.errors).toEqual([]);
- });
-
- it('should accept a list of ids to unfollow', async () => {
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
-
- const response = await callRoute(routeHandler, {}, { params: { id: '1,2,3' } });
-
- expect(response.options.body.itemsUnfollowed).toEqual(['1', '2', '3']);
- });
-
- it('should catch error and return them in array', async () => {
- const error = new Error('something went wrong');
- error.response = '{ "error": {} }';
-
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(null, { acknowledge: true });
- setHttpRequestResponse(error);
-
- const {
- options: { body: response },
- } = await callRoute(routeHandler, {}, { params: { id: '1,2' } });
-
- expect(response.itemsUnfollowed).toEqual(['1']);
- expect(response.errors[0].id).toEqual('2');
- });
- });
-});
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/__jest__/helpers.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/__jest__/helpers.ts
deleted file mode 100644
index 555fc0937c0ad..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/__jest__/helpers.ts
+++ /dev/null
@@ -1,37 +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 { RequestHandler } from 'src/core/server';
-import { kibanaResponseFactory } from '../../../../../../../../../src/core/server';
-
-export const callRoute = (
- route: RequestHandler,
- ctx = {},
- request = {},
- response = kibanaResponseFactory
-) => {
- return route(ctx as any, request as any, response);
-};
-
-export const createRouter = (indexToActionMap: Record) => {
- let index = 0;
- const routeHandlers: Record> = {};
- const addHandler = (ignoreCtxForNow: any, handler: RequestHandler) => {
- // Save handler and increment index
- routeHandlers[indexToActionMap[index]] = handler;
- index++;
- };
-
- return {
- getRoutes: () => routeHandlers,
- router: {
- get: addHandler,
- post: addHandler,
- put: addHandler,
- delete: addHandler,
- },
- };
-};
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/auto_follow_pattern.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/auto_follow_pattern.ts
deleted file mode 100644
index d458f1ccb354b..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/auto_follow_pattern.ts
+++ /dev/null
@@ -1,301 +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 { schema } from '@kbn/config-schema';
-// @ts-ignore
-import { callWithRequestFactory } from '../../lib/call_with_request_factory';
-import { isEsError } from '../../lib/is_es_error';
-// @ts-ignore
-import {
- deserializeAutoFollowPattern,
- deserializeListAutoFollowPatterns,
- serializeAutoFollowPattern,
- // @ts-ignore
-} from '../../../../common/services/auto_follow_pattern_serialization';
-
-import { licensePreRoutingFactory } from '../../lib/license_pre_routing_factory';
-import { API_BASE_PATH } from '../../../../common/constants';
-
-import { RouteDependencies } from '../types';
-import { mapErrorToKibanaHttpResponse } from '../map_to_kibana_http_error';
-
-export const registerAutoFollowPatternRoutes = ({ router, __LEGACY }: RouteDependencies) => {
- /**
- * Returns a list of all auto-follow patterns
- */
- router.get(
- {
- path: `${API_BASE_PATH}/auto_follow_patterns`,
- validate: false,
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
-
- try {
- const result = await callWithRequest('ccr.autoFollowPatterns');
- return response.ok({
- body: {
- patterns: deserializeListAutoFollowPatterns(result.patterns),
- },
- });
- } catch (err) {
- return mapErrorToKibanaHttpResponse(err);
- }
- },
- })
- );
-
- /**
- * Create an auto-follow pattern
- */
- router.post(
- {
- path: `${API_BASE_PATH}/auto_follow_patterns`,
- validate: {
- body: schema.object(
- {
- id: schema.string(),
- },
- { unknowns: 'allow' }
- ),
- },
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
- const { id, ...rest } = request.body;
- const body = serializeAutoFollowPattern(rest);
-
- /**
- * First let's make sur that an auto-follow pattern with
- * the same id does not exist.
- */
- try {
- await callWithRequest('ccr.autoFollowPattern', { id });
- // If we get here it means that an auto-follow pattern with the same id exists
- return response.conflict({
- body: `An auto-follow pattern with the name "${id}" already exists.`,
- });
- } catch (err) {
- if (err.statusCode !== 404) {
- return mapErrorToKibanaHttpResponse(err);
- }
- }
-
- try {
- return response.ok({
- body: await callWithRequest('ccr.saveAutoFollowPattern', { id, body }),
- });
- } catch (err) {
- return mapErrorToKibanaHttpResponse(err);
- }
- },
- })
- );
-
- /**
- * Update an auto-follow pattern
- */
- router.put(
- {
- path: `${API_BASE_PATH}/auto_follow_patterns/{id}`,
- validate: {
- params: schema.object({
- id: schema.string(),
- }),
- body: schema.object({}, { unknowns: 'allow' }),
- },
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
- const { id } = request.params;
- const body = serializeAutoFollowPattern(request.body);
-
- try {
- return response.ok({
- body: await callWithRequest('ccr.saveAutoFollowPattern', { id, body }),
- });
- } catch (err) {
- return mapErrorToKibanaHttpResponse(err);
- }
- },
- })
- );
-
- /**
- * Returns a single auto-follow pattern
- */
- router.get(
- {
- path: `${API_BASE_PATH}/auto_follow_patterns/{id}`,
- validate: {
- params: schema.object({
- id: schema.string(),
- }),
- },
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
- const { id } = request.params;
-
- try {
- const result = await callWithRequest('ccr.autoFollowPattern', { id });
- const autoFollowPattern = result.patterns[0];
-
- return response.ok({
- body: deserializeAutoFollowPattern(autoFollowPattern),
- });
- } catch (err) {
- return mapErrorToKibanaHttpResponse(err);
- }
- },
- })
- );
-
- /**
- * Delete an auto-follow pattern
- */
- router.delete(
- {
- path: `${API_BASE_PATH}/auto_follow_patterns/{id}`,
- validate: {
- params: schema.object({
- id: schema.string(),
- }),
- },
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
- const { id } = request.params;
- const ids = id.split(',');
-
- const itemsDeleted: string[] = [];
- const errors: Array<{ id: string; error: any }> = [];
-
- await Promise.all(
- ids.map(_id =>
- callWithRequest('ccr.deleteAutoFollowPattern', { id: _id })
- .then(() => itemsDeleted.push(_id))
- .catch((err: Error) => {
- if (isEsError(err)) {
- errors.push({ id: _id, error: mapErrorToKibanaHttpResponse(err) });
- } else {
- errors.push({ id: _id, error: mapErrorToKibanaHttpResponse(err) });
- }
- })
- )
- );
-
- return response.ok({
- body: {
- itemsDeleted,
- errors,
- },
- });
- },
- })
- );
-
- /**
- * Pause auto-follow pattern(s)
- */
- router.post(
- {
- path: `${API_BASE_PATH}/auto_follow_patterns/{id}/pause`,
- validate: {
- params: schema.object({
- id: schema.string(),
- }),
- },
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
- const { id } = request.params;
- const ids = id.split(',');
-
- const itemsPaused: string[] = [];
- const errors: Array<{ id: string; error: any }> = [];
-
- await Promise.all(
- ids.map(_id =>
- callWithRequest('ccr.pauseAutoFollowPattern', { id: _id })
- .then(() => itemsPaused.push(_id))
- .catch((err: Error) => {
- if (isEsError(err)) {
- errors.push({ id: _id, error: mapErrorToKibanaHttpResponse(err) });
- } else {
- errors.push({ id: _id, error: mapErrorToKibanaHttpResponse(err) });
- }
- })
- )
- );
-
- return response.ok({
- body: {
- itemsPaused,
- errors,
- },
- });
- },
- })
- );
-
- /**
- * Resume auto-follow pattern(s)
- */
- router.post(
- {
- path: `${API_BASE_PATH}/auto_follow_patterns/{id}/resume`,
- validate: {
- params: schema.object({
- id: schema.string(),
- }),
- },
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
- const { id } = request.params;
- const ids = id.split(',');
-
- const itemsResumed: string[] = [];
- const errors: Array<{ id: string; error: any }> = [];
-
- await Promise.all(
- ids.map(_id =>
- callWithRequest('ccr.resumeAutoFollowPattern', { id: _id })
- .then(() => itemsResumed.push(_id))
- .catch((err: Error) => {
- if (isEsError(err)) {
- errors.push({ id: _id, error: mapErrorToKibanaHttpResponse(err) });
- } else {
- errors.push({ id: _id, error: mapErrorToKibanaHttpResponse(err) });
- }
- })
- )
- );
-
- return response.ok({
- body: {
- itemsResumed,
- errors,
- },
- });
- },
- })
- );
-};
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/ccr.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/ccr.ts
deleted file mode 100644
index b08b056ad2c8a..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/ccr.ts
+++ /dev/null
@@ -1,112 +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 { API_BASE_PATH } from '../../../../common/constants';
-// @ts-ignore
-import { callWithRequestFactory } from '../../lib/call_with_request_factory';
-// @ts-ignore
-import { deserializeAutoFollowStats } from '../../lib/ccr_stats_serialization';
-import { licensePreRoutingFactory } from '../../lib/license_pre_routing_factory';
-
-import { mapErrorToKibanaHttpResponse } from '../map_to_kibana_http_error';
-import { RouteDependencies } from '../types';
-
-export const registerCcrRoutes = ({ router, __LEGACY }: RouteDependencies) => {
- /**
- * Returns Auto-follow stats
- */
- router.get(
- {
- path: `${API_BASE_PATH}/stats/auto_follow`,
- validate: false,
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
-
- try {
- const { auto_follow_stats: autoFollowStats } = await callWithRequest('ccr.stats');
-
- return response.ok({
- body: deserializeAutoFollowStats(autoFollowStats),
- });
- } catch (err) {
- return mapErrorToKibanaHttpResponse(err);
- }
- },
- })
- );
-
- /**
- * Returns whether the user has CCR permissions
- */
- router.get(
- {
- path: `${API_BASE_PATH}/permissions`,
- validate: false,
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const xpackMainPlugin = __LEGACY.server.plugins.xpack_main;
- const xpackInfo = xpackMainPlugin && xpackMainPlugin.info;
-
- if (!xpackInfo) {
- // xpackInfo is updated via poll, so it may not be available until polling has begun.
- // In this rare situation, tell the client the service is temporarily unavailable.
- return response.customError({
- statusCode: 503,
- body: 'Security info unavailable',
- });
- }
-
- const securityInfo = xpackInfo && xpackInfo.isAvailable() && xpackInfo.feature('security');
- if (!securityInfo || !securityInfo.isAvailable() || !securityInfo.isEnabled()) {
- // If security isn't enabled or available (in the case where security is enabled but license reverted to Basic) let the user use CCR.
- return response.ok({
- body: {
- hasPermission: true,
- missingClusterPrivileges: [],
- },
- });
- }
-
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
-
- try {
- const { has_all_requested: hasPermission, cluster } = await callWithRequest(
- 'ccr.permissions',
- {
- body: {
- cluster: ['manage', 'manage_ccr'],
- },
- }
- );
-
- const missingClusterPrivileges = Object.keys(cluster).reduce(
- (permissions: any, permissionName: any) => {
- if (!cluster[permissionName]) {
- permissions.push(permissionName);
- return permissions;
- }
- },
- [] as any[]
- );
-
- return response.ok({
- body: {
- hasPermission,
- missingClusterPrivileges,
- },
- });
- } catch (err) {
- return mapErrorToKibanaHttpResponse(err);
- }
- },
- })
- );
-};
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts
deleted file mode 100644
index 1d7dacf4a8688..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts
+++ /dev/null
@@ -1,357 +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 { schema } from '@kbn/config-schema';
-import {
- deserializeFollowerIndex,
- deserializeListFollowerIndices,
- serializeFollowerIndex,
- serializeAdvancedSettings,
- // @ts-ignore
-} from '../../../../common/services/follower_index_serialization';
-import { API_BASE_PATH } from '../../../../common/constants';
-// @ts-ignore
-import { removeEmptyFields } from '../../../../common/services/utils';
-// @ts-ignore
-import { callWithRequestFactory } from '../../lib/call_with_request_factory';
-import { licensePreRoutingFactory } from '../../lib/license_pre_routing_factory';
-
-import { RouteDependencies } from '../types';
-import { mapErrorToKibanaHttpResponse } from '../map_to_kibana_http_error';
-
-export const registerFollowerIndexRoutes = ({ router, __LEGACY }: RouteDependencies) => {
- /**
- * Returns a list of all follower indices
- */
- router.get(
- {
- path: `${API_BASE_PATH}/follower_indices`,
- validate: false,
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
-
- try {
- const { follower_indices: followerIndices } = await callWithRequest('ccr.info', {
- id: '_all',
- });
-
- const {
- follow_stats: { indices: followerIndicesStats },
- } = await callWithRequest('ccr.stats');
-
- const followerIndicesStatsMap = followerIndicesStats.reduce((map: any, stats: any) => {
- map[stats.index] = stats;
- return map;
- }, {});
-
- const collatedFollowerIndices = followerIndices.map((followerIndex: any) => {
- return {
- ...followerIndex,
- ...followerIndicesStatsMap[followerIndex.follower_index],
- };
- });
-
- return response.ok({
- body: {
- indices: deserializeListFollowerIndices(collatedFollowerIndices),
- },
- });
- } catch (err) {
- return mapErrorToKibanaHttpResponse(err);
- }
- },
- })
- );
-
- /**
- * Returns a single follower index pattern
- */
- router.get(
- {
- path: `${API_BASE_PATH}/follower_indices/{id}`,
- validate: {
- params: schema.object({
- id: schema.string(),
- }),
- },
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
- const { id } = request.params;
-
- try {
- const { follower_indices: followerIndices } = await callWithRequest('ccr.info', { id });
-
- const followerIndexInfo = followerIndices && followerIndices[0];
-
- if (!followerIndexInfo) {
- return response.notFound({
- body: `The follower index "${id}" does not exist.`,
- });
- }
-
- // If this follower is paused, skip call to ES stats api since it will return 404
- if (followerIndexInfo.status === 'paused') {
- return response.ok({
- body: deserializeFollowerIndex({
- ...followerIndexInfo,
- }),
- });
- } else {
- const {
- indices: followerIndicesStats,
- } = await callWithRequest('ccr.followerIndexStats', { id });
-
- return response.ok({
- body: deserializeFollowerIndex({
- ...followerIndexInfo,
- ...(followerIndicesStats ? followerIndicesStats[0] : {}),
- }),
- });
- }
- } catch (err) {
- return mapErrorToKibanaHttpResponse(err);
- }
- },
- })
- );
-
- /**
- * Create a follower index
- */
- router.post(
- {
- path: `${API_BASE_PATH}/follower_indices`,
- validate: {
- body: schema.object(
- {
- name: schema.string(),
- },
- { unknowns: 'allow' }
- ),
- },
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
- const { name, ...rest } = request.body;
- const body = removeEmptyFields(serializeFollowerIndex(rest));
-
- try {
- return response.ok({
- body: await callWithRequest('ccr.saveFollowerIndex', { name, body }),
- });
- } catch (err) {
- return mapErrorToKibanaHttpResponse(err);
- }
- },
- })
- );
-
- /**
- * Edit a follower index
- */
- router.put(
- {
- path: `${API_BASE_PATH}/follower_indices/{id}`,
- validate: {
- params: schema.object({ id: schema.string() }),
- body: schema.object({
- maxReadRequestOperationCount: schema.maybe(schema.number()),
- maxOutstandingReadRequests: schema.maybe(schema.number()),
- maxReadRequestSize: schema.maybe(schema.string()), // byte value
- maxWriteRequestOperationCount: schema.maybe(schema.number()),
- maxWriteRequestSize: schema.maybe(schema.string()), // byte value
- maxOutstandingWriteRequests: schema.maybe(schema.number()),
- maxWriteBufferCount: schema.maybe(schema.number()),
- maxWriteBufferSize: schema.maybe(schema.string()), // byte value
- maxRetryDelay: schema.maybe(schema.string()), // time value
- readPollTimeout: schema.maybe(schema.string()), // time value
- }),
- },
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
- const { id } = request.params;
-
- // We need to first pause the follower and then resume it passing the advanced settings
- try {
- const { follower_indices: followerIndices } = await callWithRequest('ccr.info', { id });
- const followerIndexInfo = followerIndices && followerIndices[0];
- if (!followerIndexInfo) {
- return response.notFound({ body: `The follower index "${id}" does not exist.` });
- }
-
- // Retrieve paused state instead of pulling it from the payload to ensure it's not stale.
- const isPaused = followerIndexInfo.status === 'paused';
- // Pause follower if not already paused
- if (!isPaused) {
- await callWithRequest('ccr.pauseFollowerIndex', { id });
- }
-
- // Resume follower
- const body = removeEmptyFields(serializeAdvancedSettings(request.body));
- return response.ok({
- body: await callWithRequest('ccr.resumeFollowerIndex', { id, body }),
- });
- } catch (err) {
- return mapErrorToKibanaHttpResponse(err);
- }
- },
- })
- );
-
- /**
- * Pauses a follower index
- */
- router.put(
- {
- path: `${API_BASE_PATH}/follower_indices/{id}/pause`,
- validate: {
- params: schema.object({ id: schema.string() }),
- },
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
- const { id } = request.params;
- const ids = id.split(',');
-
- const itemsPaused: string[] = [];
- const errors: Array<{ id: string; error: any }> = [];
-
- await Promise.all(
- ids.map(_id =>
- callWithRequest('ccr.pauseFollowerIndex', { id: _id })
- .then(() => itemsPaused.push(_id))
- .catch((err: Error) => {
- errors.push({ id: _id, error: mapErrorToKibanaHttpResponse(err) });
- })
- )
- );
-
- return response.ok({
- body: {
- itemsPaused,
- errors,
- },
- });
- },
- })
- );
-
- /**
- * Resumes a follower index
- */
- router.put(
- {
- path: `${API_BASE_PATH}/follower_indices/{id}/resume`,
- validate: {
- params: schema.object({ id: schema.string() }),
- },
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
- const { id } = request.params;
- const ids = id.split(',');
-
- const itemsResumed: string[] = [];
- const errors: Array<{ id: string; error: any }> = [];
-
- await Promise.all(
- ids.map(_id =>
- callWithRequest('ccr.resumeFollowerIndex', { id: _id })
- .then(() => itemsResumed.push(_id))
- .catch((err: Error) => {
- errors.push({ id: _id, error: mapErrorToKibanaHttpResponse(err) });
- })
- )
- );
-
- return response.ok({
- body: {
- itemsResumed,
- errors,
- },
- });
- },
- })
- );
-
- /**
- * Unfollow follower index's leader index
- */
- router.put(
- {
- path: `${API_BASE_PATH}/follower_indices/{id}/unfollow`,
- validate: {
- params: schema.object({ id: schema.string() }),
- },
- },
- licensePreRoutingFactory({
- __LEGACY,
- requestHandler: async (ctx, request, response) => {
- const callWithRequest = callWithRequestFactory(__LEGACY.server, request);
- const { id } = request.params;
- const ids = id.split(',');
-
- const itemsUnfollowed: string[] = [];
- const itemsNotOpen: string[] = [];
- const errors: Array<{ id: string; error: any }> = [];
-
- await Promise.all(
- ids.map(async _id => {
- try {
- // Try to pause follower, let it fail silently since it may already be paused
- try {
- await callWithRequest('ccr.pauseFollowerIndex', { id: _id });
- } catch (e) {
- // Swallow errors
- }
-
- // Close index
- await callWithRequest('indices.close', { index: _id });
-
- // Unfollow leader
- await callWithRequest('ccr.unfollowLeaderIndex', { id: _id });
-
- // Try to re-open the index, store failures in a separate array to surface warnings in the UI
- // This will allow users to query their index normally after unfollowing
- try {
- await callWithRequest('indices.open', { index: _id });
- } catch (e) {
- itemsNotOpen.push(_id);
- }
-
- // Push success
- itemsUnfollowed.push(_id);
- } catch (err) {
- errors.push({ id: _id, error: mapErrorToKibanaHttpResponse(err) });
- }
- })
- );
-
- return response.ok({
- body: {
- itemsUnfollowed,
- itemsNotOpen,
- errors,
- },
- });
- },
- })
- );
-};
diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/map_to_kibana_http_error.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/map_to_kibana_http_error.ts
deleted file mode 100644
index 6a81bd26dc47d..0000000000000
--- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/map_to_kibana_http_error.ts
+++ /dev/null
@@ -1,26 +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 { kibanaResponseFactory } from '../../../../../../../src/core/server';
-// @ts-ignore
-import { wrapEsError } from '../lib/error_wrappers';
-import { isEsError } from '../lib/is_es_error';
-
-export const mapErrorToKibanaHttpResponse = (err: any) => {
- if (isEsError(err)) {
- const { statusCode, message, body } = wrapEsError(err);
- return kibanaResponseFactory.customError({
- statusCode,
- body: {
- message,
- attributes: {
- cause: body?.cause,
- },
- },
- });
- }
- return kibanaResponseFactory.internalError(err);
-};
diff --git a/x-pack/legacy/plugins/monitoring/README.md b/x-pack/legacy/plugins/monitoring/README.md
index 3659f4d2fa0f7..e9ececa8c6350 100644
--- a/x-pack/legacy/plugins/monitoring/README.md
+++ b/x-pack/legacy/plugins/monitoring/README.md
@@ -72,8 +72,8 @@ cluster.
1. Set the Kibana config:
```
% cat config/kibana.dev.yml
- xpack.monitoring.elasticsearch:
- url: "http://localhost:9210"
+ monitoring.ui.elasticsearch:
+ hosts: "http://localhost:9210"
username: "kibana"
password: "changeme"
```
diff --git a/x-pack/legacy/plugins/monitoring/public/components/apm/instances/instances.js b/x-pack/legacy/plugins/monitoring/public/components/apm/instances/instances.js
index f3a888bf9e905..a48fbc51341f1 100644
--- a/x-pack/legacy/plugins/monitoring/public/components/apm/instances/instances.js
+++ b/x-pack/legacy/plugins/monitoring/public/components/apm/instances/instances.js
@@ -18,6 +18,7 @@ import {
} from '@elastic/eui';
import { Status } from './status';
import { formatMetric } from '../../../lib/format_number';
+import { getSafeForExternalLink } from '../../../lib/get_safe_for_external_link';
import { formatTimestampToDuration } from '../../../../common';
import { i18n } from '@kbn/i18n';
import { APM_SYSTEM_ID } from '../../../../common/constants';
@@ -56,7 +57,10 @@ function getColumns(setupMode) {
return (