mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Move ILM out of legacy (#61915)
* Rename IndexMgmtSetup to IndexManagementPluginSetup. * Remove unused fetch index template route and related tests. * Remove unnecessary custom styles.
This commit is contained in:
parent
93b34632c0
commit
982c0da78e
177 changed files with 1264 additions and 1828 deletions
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
|
@ -180,7 +180,7 @@
|
|||
/src/plugins/console/ @elastic/es-ui
|
||||
/src/plugins/es_ui_shared/ @elastic/es-ui
|
||||
/x-pack/legacy/plugins/cross_cluster_replication/ @elastic/es-ui
|
||||
/x-pack/legacy/plugins/index_lifecycle_management/ @elastic/es-ui
|
||||
/x-pack/plugins/index_lifecycle_management/ @elastic/es-ui
|
||||
/x-pack/legacy/plugins/index_management/ @elastic/es-ui
|
||||
/x-pack/legacy/plugins/license_management/ @elastic/es-ui
|
||||
/x-pack/legacy/plugins/rollup/ @elastic/es-ui
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
"xpack.graph": ["legacy/plugins/graph", "plugins/graph"],
|
||||
"xpack.grokDebugger": "plugins/grokdebugger",
|
||||
"xpack.idxMgmt": "plugins/index_management",
|
||||
"xpack.indexLifecycleMgmt": "legacy/plugins/index_lifecycle_management",
|
||||
"xpack.indexLifecycleMgmt": "plugins/index_lifecycle_management",
|
||||
"xpack.infra": "plugins/infra",
|
||||
"xpack.ingestManager": "plugins/ingest_manager",
|
||||
"xpack.lens": "legacy/plugins/lens",
|
||||
|
|
|
@ -16,7 +16,6 @@ import { beats } from './legacy/plugins/beats_management';
|
|||
import { apm } from './legacy/plugins/apm';
|
||||
import { maps } from './legacy/plugins/maps';
|
||||
import { indexManagement } from './legacy/plugins/index_management';
|
||||
import { indexLifecycleManagement } from './legacy/plugins/index_lifecycle_management';
|
||||
import { spaces } from './legacy/plugins/spaces';
|
||||
import { canvas } from './legacy/plugins/canvas';
|
||||
import { infra } from './legacy/plugins/infra';
|
||||
|
@ -50,7 +49,6 @@ module.exports = function(kibana) {
|
|||
maps(kibana),
|
||||
canvas(kibana),
|
||||
indexManagement(kibana),
|
||||
indexLifecycleManagement(kibana),
|
||||
infra(kibana),
|
||||
taskManager(kibana),
|
||||
rollup(kibana),
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { get } from 'lodash';
|
||||
import { IndexMgmtSetup } from '../../../../../plugins/index_management/public';
|
||||
import { IndexManagementPluginSetup } from '../../../../../plugins/index_management/public';
|
||||
|
||||
const propertyPath = 'isFollowerIndex';
|
||||
|
||||
|
@ -21,7 +21,7 @@ const followerBadgeExtension = {
|
|||
filterExpression: 'isFollowerIndex:true',
|
||||
};
|
||||
|
||||
export const extendIndexManagement = (indexManagement?: IndexMgmtSetup) => {
|
||||
export const extendIndexManagement = (indexManagement?: IndexManagementPluginSetup) => {
|
||||
if (indexManagement) {
|
||||
indexManagement.extensionsService.addBadge(followerBadgeExtension);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import {
|
|||
DocLinksStart,
|
||||
} from 'src/core/public';
|
||||
|
||||
import { IndexMgmtSetup } from '../../../../../plugins/index_management/public';
|
||||
import { IndexManagementPluginSetup } from '../../../../../plugins/index_management/public';
|
||||
|
||||
// @ts-ignore;
|
||||
import { setHttpClient } from './app/services/api';
|
||||
|
@ -21,7 +21,7 @@ import { setNotifications } from './app/services/notifications';
|
|||
import { extendIndexManagement } from './extend_index_management';
|
||||
|
||||
interface PluginDependencies {
|
||||
indexManagement: IndexMgmtSetup;
|
||||
indexManagement: IndexManagementPluginSetup;
|
||||
__LEGACY: {
|
||||
chrome: any;
|
||||
MANAGEMENT_BREADCRUMB: ChromeBreadcrumb;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { Plugin, PluginInitializerContext, CoreSetup } from 'src/core/server';
|
||||
|
||||
import { IndexMgmtSetup } from '../../../../../plugins/index_management/server';
|
||||
import { IndexManagementPluginSetup } from '../../../../../plugins/index_management/server';
|
||||
|
||||
// @ts-ignore
|
||||
import { registerLicenseChecker } from './lib/register_license_checker';
|
||||
|
@ -15,7 +15,7 @@ import { registerRoutes } from './routes/register_routes';
|
|||
import { ccrDataEnricher } from './cross_cluster_replication_data';
|
||||
|
||||
interface PluginDependencies {
|
||||
indexManagement: IndexMgmtSetup;
|
||||
indexManagement: IndexManagementPluginSetup;
|
||||
__LEGACY: {
|
||||
server: any;
|
||||
ccrUIEnabled: boolean;
|
||||
|
|
|
@ -1,62 +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 { Legacy } from 'kibana';
|
||||
import { resolve } from 'path';
|
||||
import { PLUGIN } from './common/constants';
|
||||
import { Plugin as IndexLifecycleManagementPlugin } from './plugin';
|
||||
import { createShim } from './shim';
|
||||
|
||||
export function indexLifecycleManagement(kibana: any) {
|
||||
return new kibana.Plugin({
|
||||
id: PLUGIN.ID,
|
||||
configPrefix: 'xpack.ilm',
|
||||
publicDir: resolve(__dirname, 'public'),
|
||||
require: ['kibana', 'elasticsearch', 'xpack_main', 'index_management'],
|
||||
uiExports: {
|
||||
styleSheetPaths: resolve(__dirname, 'public/np_ready/application/index.scss'),
|
||||
managementSections: ['plugins/index_lifecycle_management/legacy'],
|
||||
injectDefaultVars(server: Legacy.Server) {
|
||||
const config = server.config();
|
||||
return {
|
||||
ilmUiEnabled: config.get('xpack.ilm.ui.enabled'),
|
||||
};
|
||||
},
|
||||
},
|
||||
config: (Joi: any) => {
|
||||
return Joi.object({
|
||||
// display menu item
|
||||
ui: Joi.object({
|
||||
enabled: Joi.boolean().default(true),
|
||||
}).default(),
|
||||
|
||||
// enable plugin
|
||||
enabled: Joi.boolean().default(true),
|
||||
|
||||
filteredNodeAttributes: Joi.array()
|
||||
.items(Joi.string())
|
||||
.default([]),
|
||||
}).default();
|
||||
},
|
||||
isEnabled(config: any) {
|
||||
return (
|
||||
config.get('xpack.ilm.enabled') &&
|
||||
config.has('xpack.index_management.enabled') &&
|
||||
config.get('xpack.index_management.enabled')
|
||||
);
|
||||
},
|
||||
init(server: Legacy.Server) {
|
||||
const core = server.newPlatform.setup.core;
|
||||
const plugins = {};
|
||||
const __LEGACY = createShim(server);
|
||||
|
||||
const indexLifecycleManagementPlugin = new IndexLifecycleManagementPlugin();
|
||||
|
||||
// Set up plugin.
|
||||
indexLifecycleManagementPlugin.setup(core, plugins, __LEGACY);
|
||||
},
|
||||
});
|
||||
}
|
|
@ -1,54 +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 } from 'kibana/server';
|
||||
import { LegacySetup } from './shim';
|
||||
import { registerLicenseChecker } from './server/lib/register_license_checker';
|
||||
import { registerIndexRoutes } from './server/routes/api/index';
|
||||
import { registerNodesRoutes } from './server/routes/api/nodes';
|
||||
import { registerPoliciesRoutes } from './server/routes/api/policies';
|
||||
import { registerTemplatesRoutes } from './server/routes/api/templates';
|
||||
|
||||
const indexLifecycleDataEnricher = async (indicesList: any, callWithRequest: any) => {
|
||||
if (!indicesList || !indicesList.length) {
|
||||
return;
|
||||
}
|
||||
const params = {
|
||||
path: '/*/_ilm/explain',
|
||||
method: 'GET',
|
||||
};
|
||||
const { indices: ilmIndicesData } = await callWithRequest('transport.request', params);
|
||||
return indicesList.map((index: any): any => {
|
||||
return {
|
||||
...index,
|
||||
ilm: { ...(ilmIndicesData[index.name] || {}) },
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export class Plugin {
|
||||
public setup(core: CoreSetup, plugins: any, __LEGACY: LegacySetup): void {
|
||||
const { server } = __LEGACY;
|
||||
|
||||
registerLicenseChecker(server);
|
||||
|
||||
// Register routes.
|
||||
registerIndexRoutes(server);
|
||||
registerNodesRoutes(server);
|
||||
registerPoliciesRoutes(server);
|
||||
registerTemplatesRoutes(server);
|
||||
|
||||
const serverPlugins = server.newPlatform.setup.plugins as any;
|
||||
|
||||
if (
|
||||
server.config().get('xpack.ilm.ui.enabled') &&
|
||||
serverPlugins.indexManagement &&
|
||||
serverPlugins.indexManagement.indexDataEnricher
|
||||
) {
|
||||
serverPlugins.indexManagement.indexDataEnricher.add(indexLifecycleDataEnricher);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,109 +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 { App } from 'src/core/public';
|
||||
|
||||
/* Legacy Imports */
|
||||
import { npSetup, npStart } from 'ui/new_platform';
|
||||
import chrome from 'ui/chrome';
|
||||
import routes from 'ui/routes';
|
||||
import { management } from 'ui/management';
|
||||
import { createUiStatsReporter } from '../../../../../src/legacy/core_plugins/ui_metric/public';
|
||||
|
||||
import { PLUGIN, BASE_PATH } from '../common/constants';
|
||||
import { createPlugin } from './np_ready';
|
||||
import { addAllExtensions } from './np_ready/extend_index_management';
|
||||
|
||||
if (chrome.getInjected('ilmUiEnabled')) {
|
||||
// We have to initialize this outside of the NP lifecycle, otherwise these extensions won't
|
||||
// be available in Index Management unless the user visits ILM first.
|
||||
if ((npSetup.plugins as any).indexManagement) {
|
||||
addAllExtensions((npSetup.plugins as any).indexManagement.extensionsService);
|
||||
}
|
||||
|
||||
// This method handles the cleanup needed when route is scope is destroyed. It also prevents Angular
|
||||
// from destroying scope when route changes and both old route and new route are this same route.
|
||||
const manageAngularLifecycle = ($scope: any, $route: any, unmount: () => void) => {
|
||||
const lastRoute = $route.current;
|
||||
const deregister = $scope.$on('$locationChangeSuccess', () => {
|
||||
const currentRoute = $route.current;
|
||||
// if templates are the same we are on the same route
|
||||
if (lastRoute.$$route.template === currentRoute.$$route.template) {
|
||||
// this prevents angular from destroying scope
|
||||
$route.current = lastRoute;
|
||||
}
|
||||
});
|
||||
$scope.$on('$destroy', () => {
|
||||
if (deregister) {
|
||||
deregister();
|
||||
}
|
||||
unmount();
|
||||
});
|
||||
};
|
||||
|
||||
// Once this app no longer depends upon Angular's routing (e.g. for the "redirect" service), we can
|
||||
// use the Management plugin's API to register this app within the Elasticsearch section.
|
||||
const esSection = management.getSection('elasticsearch');
|
||||
esSection.register('index_lifecycle_policies', {
|
||||
visible: true,
|
||||
display: PLUGIN.TITLE,
|
||||
order: 2,
|
||||
url: `#${BASE_PATH}policies`,
|
||||
});
|
||||
|
||||
const REACT_ROOT_ID = 'indexLifecycleManagementReactRoot';
|
||||
|
||||
const template = `<kbn-management-app section="elasticsearch/index_lifecycle_policies">
|
||||
<div id="${REACT_ROOT_ID}" class="policyTable__horizontalScrollContainer"/>
|
||||
</kbn-management-app>
|
||||
`;
|
||||
|
||||
routes.when(`${BASE_PATH}:view?/:action?/:id?`, {
|
||||
template,
|
||||
controllerAs: 'indexLifecycleManagement',
|
||||
controller: class IndexLifecycleManagementController {
|
||||
constructor($scope: any, $route: any, kbnUrl: any, $rootScope: any) {
|
||||
$scope.$$postDigest(() => {
|
||||
const element = document.getElementById(REACT_ROOT_ID)!;
|
||||
const { core } = npSetup;
|
||||
|
||||
const coreDependencies = {
|
||||
...core,
|
||||
application: {
|
||||
...core.application,
|
||||
async register(app: App<any>) {
|
||||
const unmountApp = await app.mount({ ...npStart } as any, {
|
||||
element,
|
||||
appBasePath: '',
|
||||
onAppLeave: () => undefined,
|
||||
// TODO: adapt to use Core's ScopedHistory
|
||||
history: {} as any,
|
||||
});
|
||||
manageAngularLifecycle($scope, $route, unmountApp as any);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// The Plugin interface won't allow us to pass __LEGACY as a third argument, so we'll just
|
||||
// sneak it inside of the plugins argument for now.
|
||||
const pluginDependencies = {
|
||||
__LEGACY: {
|
||||
redirect: (path: string) => {
|
||||
$scope.$evalAsync(() => {
|
||||
kbnUrl.redirect(path);
|
||||
});
|
||||
},
|
||||
createUiStatsReporter,
|
||||
},
|
||||
};
|
||||
|
||||
const plugin = createPlugin({} as any);
|
||||
plugin.setup(coreDependencies, pluginDependencies);
|
||||
});
|
||||
}
|
||||
} as any,
|
||||
} as any);
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
.policyTable__horizontalScrollContainer {
|
||||
overflow-x: auto;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.policyTable__horizontalScroll {
|
||||
min-width: 800px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.policyTable__link {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.ilmEditPolicyPageContent {
|
||||
max-width: 1200px !important;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
// Import the EUI global scope so we can use EUI constants
|
||||
@import 'src/legacy/ui/public/styles/_styling_constants';
|
||||
@import 'index_lifecycle_management';
|
|
@ -1,63 +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 React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import { DocLinksStart, ToastsSetup, HttpSetup, FatalErrorsSetup } from 'src/core/public';
|
||||
|
||||
import { App } from './app';
|
||||
import { indexLifecycleManagementStore } from './store';
|
||||
import { init as initHttp } from './services/http';
|
||||
import { init as initNavigation } from './services/navigation';
|
||||
import { init as initDocumentation } from './services/documentation';
|
||||
import { init as initUiMetric } from './services/ui_metric';
|
||||
import { init as initNotification } from './services/notification';
|
||||
|
||||
export interface LegacySetup {
|
||||
redirect: any;
|
||||
createUiStatsReporter: any;
|
||||
}
|
||||
|
||||
interface AppDependencies {
|
||||
legacy: LegacySetup;
|
||||
I18nContext: any;
|
||||
http: HttpSetup;
|
||||
toasts: ToastsSetup;
|
||||
fatalErrors: FatalErrorsSetup;
|
||||
docLinks: DocLinksStart;
|
||||
element: HTMLElement;
|
||||
}
|
||||
|
||||
export const renderApp = (appDependencies: AppDependencies) => {
|
||||
const {
|
||||
legacy: { redirect, createUiStatsReporter },
|
||||
I18nContext,
|
||||
http,
|
||||
toasts,
|
||||
fatalErrors,
|
||||
docLinks: { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION },
|
||||
element,
|
||||
} = appDependencies;
|
||||
|
||||
// Initialize services
|
||||
initHttp(http);
|
||||
initNavigation(redirect);
|
||||
initDocumentation(`${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`);
|
||||
initUiMetric(createUiStatsReporter);
|
||||
initNotification(toasts, fatalErrors);
|
||||
|
||||
render(
|
||||
<I18nContext>
|
||||
<Provider store={indexLifecycleManagementStore()}>
|
||||
<App />
|
||||
</Provider>
|
||||
</I18nContext>,
|
||||
element
|
||||
);
|
||||
|
||||
return () => unmountComponentAtNode(element);
|
||||
};
|
|
@ -1,81 +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 {
|
||||
UIM_POLICY_DELETE,
|
||||
UIM_POLICY_ATTACH_INDEX,
|
||||
UIM_POLICY_ATTACH_INDEX_TEMPLATE,
|
||||
UIM_POLICY_DETACH_INDEX,
|
||||
UIM_INDEX_RETRY_STEP,
|
||||
} from '../constants';
|
||||
|
||||
import { trackUiMetric } from './ui_metric';
|
||||
import { sendGet, sendPost, sendDelete } from './http';
|
||||
|
||||
// The extend_index_management module that we support an injected httpClient here.
|
||||
|
||||
export async function loadNodes(httpClient) {
|
||||
return await sendGet(`nodes/list`, httpClient);
|
||||
}
|
||||
|
||||
export async function loadNodeDetails(selectedNodeAttrs, httpClient) {
|
||||
return await sendGet(`nodes/${selectedNodeAttrs}/details`, httpClient);
|
||||
}
|
||||
|
||||
export async function loadIndexTemplates(httpClient) {
|
||||
return await sendGet(`templates`, httpClient);
|
||||
}
|
||||
|
||||
export async function loadIndexTemplate(templateName, httpClient) {
|
||||
if (!templateName) {
|
||||
return {};
|
||||
}
|
||||
return await sendGet(`templates/${templateName}`, httpClient);
|
||||
}
|
||||
|
||||
export async function loadPolicies(withIndices, httpClient) {
|
||||
const query = withIndices ? '?withIndices=true' : '';
|
||||
return await sendGet('policies', query, httpClient);
|
||||
}
|
||||
|
||||
export async function savePolicy(policy, httpClient) {
|
||||
return await sendPost(`policies`, policy, httpClient);
|
||||
}
|
||||
|
||||
export async function deletePolicy(policyName, httpClient) {
|
||||
const response = await sendDelete(`policies/${encodeURIComponent(policyName)}`, httpClient);
|
||||
// Only track successful actions.
|
||||
trackUiMetric('count', UIM_POLICY_DELETE);
|
||||
return response;
|
||||
}
|
||||
|
||||
export const retryLifecycleForIndex = async (indexNames, httpClient) => {
|
||||
const response = await sendPost(`index/retry`, { indexNames }, httpClient);
|
||||
// Only track successful actions.
|
||||
trackUiMetric('count', UIM_INDEX_RETRY_STEP);
|
||||
return response;
|
||||
};
|
||||
|
||||
export const removeLifecycleForIndex = async (indexNames, httpClient) => {
|
||||
const response = await sendPost(`index/remove`, { indexNames }, httpClient);
|
||||
// Only track successful actions.
|
||||
trackUiMetric('count', UIM_POLICY_DETACH_INDEX);
|
||||
return response;
|
||||
};
|
||||
|
||||
export const addLifecyclePolicyToIndex = async (body, httpClient) => {
|
||||
const response = await sendPost(`index/add`, body, httpClient);
|
||||
// Only track successful actions.
|
||||
trackUiMetric('count', UIM_POLICY_ATTACH_INDEX);
|
||||
return response;
|
||||
};
|
||||
|
||||
export const addLifecyclePolicyToTemplate = async (body, httpClient) => {
|
||||
const response = await sendPost(`template`, body, httpClient);
|
||||
// Only track successful actions.
|
||||
trackUiMetric('count', UIM_POLICY_ATTACH_INDEX_TEMPLATE);
|
||||
return response;
|
||||
};
|
|
@ -1,58 +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, CoreStart, Plugin } from 'src/core/public';
|
||||
import { PLUGIN } from '../../common/constants';
|
||||
import { LegacySetup } from './application';
|
||||
|
||||
interface PluginsSetup {
|
||||
__LEGACY: LegacySetup;
|
||||
}
|
||||
|
||||
export class IndexLifecycleManagementPlugin implements Plugin<void, void, any, any> {
|
||||
setup(core: CoreSetup, plugins: PluginsSetup) {
|
||||
// Extract individual core dependencies.
|
||||
const {
|
||||
application,
|
||||
notifications: { toasts },
|
||||
fatalErrors,
|
||||
http,
|
||||
} = core;
|
||||
|
||||
// The Plugin interface won't allow us to pass __LEGACY as a third argument, so we'll just
|
||||
// sneak it inside of the plugins parameter for now.
|
||||
const { __LEGACY } = plugins;
|
||||
|
||||
application.register({
|
||||
id: PLUGIN.ID,
|
||||
title: PLUGIN.TITLE,
|
||||
async mount(config, mountPoint) {
|
||||
const {
|
||||
core: {
|
||||
docLinks,
|
||||
i18n: { Context: I18nContext },
|
||||
},
|
||||
} = config;
|
||||
|
||||
const { element } = mountPoint;
|
||||
const { renderApp } = await import('./application');
|
||||
|
||||
// Inject all dependencies into our app.
|
||||
return renderApp({
|
||||
legacy: { ...__LEGACY },
|
||||
I18nContext,
|
||||
http,
|
||||
toasts,
|
||||
fatalErrors,
|
||||
docLinks,
|
||||
element,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
start(core: CoreStart, plugins: any) {}
|
||||
stop() {}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { once } from 'lodash';
|
||||
import { Legacy } from 'kibana';
|
||||
|
||||
const callWithRequest = once((server: Legacy.Server): any => {
|
||||
const cluster = server.plugins.elasticsearch.getCluster('data');
|
||||
return cluster.callWithRequest;
|
||||
});
|
||||
|
||||
export const callWithRequestFactory = (server: Legacy.Server, request: any) => {
|
||||
return (...args: any[]) => {
|
||||
return callWithRequest(server)(request, ...args);
|
||||
};
|
||||
};
|
|
@ -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';
|
|
@ -1,145 +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 { set } from 'lodash';
|
||||
import { checkLicense } from '../check_license';
|
||||
|
||||
describe('check_license', function() {
|
||||
let mockLicenseInfo;
|
||||
beforeEach(() => (mockLicenseInfo = {}));
|
||||
|
||||
describe('license information is undefined', () => {
|
||||
beforeEach(() => (mockLicenseInfo = undefined));
|
||||
|
||||
it('should set isAvailable to false', () => {
|
||||
expect(checkLicense(mockLicenseInfo).isAvailable).to.be(false);
|
||||
});
|
||||
|
||||
it('should set showLinks to true', () => {
|
||||
expect(checkLicense(mockLicenseInfo).showLinks).to.be(true);
|
||||
});
|
||||
|
||||
it('should set enableLinks to false', () => {
|
||||
expect(checkLicense(mockLicenseInfo).enableLinks).to.be(false);
|
||||
});
|
||||
|
||||
it('should set a message', () => {
|
||||
expect(checkLicense(mockLicenseInfo).message).to.not.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('license information is not available', () => {
|
||||
beforeEach(() => (mockLicenseInfo.isAvailable = () => false));
|
||||
|
||||
it('should set isAvailable to false', () => {
|
||||
expect(checkLicense(mockLicenseInfo).isAvailable).to.be(false);
|
||||
});
|
||||
|
||||
it('should set showLinks to true', () => {
|
||||
expect(checkLicense(mockLicenseInfo).showLinks).to.be(true);
|
||||
});
|
||||
|
||||
it('should set enableLinks to false', () => {
|
||||
expect(checkLicense(mockLicenseInfo).enableLinks).to.be(false);
|
||||
});
|
||||
|
||||
it('should set a message', () => {
|
||||
expect(checkLicense(mockLicenseInfo).message).to.not.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('license information is available', () => {
|
||||
beforeEach(() => {
|
||||
mockLicenseInfo.isAvailable = () => true;
|
||||
set(mockLicenseInfo, 'license.getType', () => 'basic');
|
||||
});
|
||||
|
||||
describe('& license is > basic', () => {
|
||||
beforeEach(() => set(mockLicenseInfo, 'license.isOneOf', () => true));
|
||||
|
||||
describe('& license is active', () => {
|
||||
beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => true));
|
||||
|
||||
it('should set isAvailable to true', () => {
|
||||
expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true);
|
||||
});
|
||||
|
||||
it('should set showLinks to true', () => {
|
||||
expect(checkLicense(mockLicenseInfo).showLinks).to.be(true);
|
||||
});
|
||||
|
||||
it('should set enableLinks to true', () => {
|
||||
expect(checkLicense(mockLicenseInfo).enableLinks).to.be(true);
|
||||
});
|
||||
|
||||
it('should not set a message', () => {
|
||||
expect(checkLicense(mockLicenseInfo).message).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('& license is expired', () => {
|
||||
beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => false));
|
||||
|
||||
it('should set isAvailable to false', () => {
|
||||
expect(checkLicense(mockLicenseInfo).isAvailable).to.be(false);
|
||||
});
|
||||
|
||||
it('should set showLinks to true', () => {
|
||||
expect(checkLicense(mockLicenseInfo).showLinks).to.be(true);
|
||||
});
|
||||
|
||||
it('should set enableLinks to false', () => {
|
||||
expect(checkLicense(mockLicenseInfo).enableLinks).to.be(false);
|
||||
});
|
||||
|
||||
it('should set a message', () => {
|
||||
expect(checkLicense(mockLicenseInfo).message).to.not.be(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('& license is basic', () => {
|
||||
beforeEach(() => set(mockLicenseInfo, 'license.isOneOf', () => true));
|
||||
|
||||
describe('& license is active', () => {
|
||||
beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => true));
|
||||
|
||||
it('should set isAvailable to true', () => {
|
||||
expect(checkLicense(mockLicenseInfo).isAvailable).to.be(true);
|
||||
});
|
||||
|
||||
it('should set showLinks to true', () => {
|
||||
expect(checkLicense(mockLicenseInfo).showLinks).to.be(true);
|
||||
});
|
||||
|
||||
it('should set enableLinks to true', () => {
|
||||
expect(checkLicense(mockLicenseInfo).enableLinks).to.be(true);
|
||||
});
|
||||
|
||||
it('should not set a message', () => {
|
||||
expect(checkLicense(mockLicenseInfo).message).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('& license is expired', () => {
|
||||
beforeEach(() => set(mockLicenseInfo, 'license.isActive', () => false));
|
||||
|
||||
it('should set isAvailable to false', () => {
|
||||
expect(checkLicense(mockLicenseInfo).isAvailable).to.be(false);
|
||||
});
|
||||
|
||||
it('should set showLinks to true', () => {
|
||||
expect(checkLicense(mockLicenseInfo).showLinks).to.be(true);
|
||||
});
|
||||
|
||||
it('should set a message', () => {
|
||||
expect(checkLicense(mockLicenseInfo).message).to.not.be(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,66 +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: any): any {
|
||||
const pluginName = 'Index Lifecycle Policies';
|
||||
|
||||
// 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.indexLifecycleMgmt.checkLicense.errorUnavailableMessage', {
|
||||
defaultMessage:
|
||||
'You cannot use {pluginName} because license information is not available at this time.',
|
||||
values: { pluginName },
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
const VALID_LICENSE_MODES = ['basic', 'standard', 'gold', 'platinum', 'enterprise', 'trial'];
|
||||
|
||||
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,
|
||||
showLinks: false,
|
||||
message: i18n.translate('xpack.indexLifecycleMgmt.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: false,
|
||||
showLinks: true,
|
||||
enableLinks: false,
|
||||
message: i18n.translate('xpack.indexLifecycleMgmt.checkLicense.errorExpiredMessage', {
|
||||
defaultMessage:
|
||||
'You cannot use {pluginName} because your {licenseType} license has expired.',
|
||||
values: { pluginName, licenseType },
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
// License is valid and active
|
||||
return {
|
||||
isAvailable: true,
|
||||
showLinks: true,
|
||||
enableLinks: true,
|
||||
};
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { wrapCustomError } from '../wrap_custom_error';
|
||||
|
||||
describe('wrap_custom_error', () => {
|
||||
describe('#wrapCustomError', () => {
|
||||
it('should return a Boom object', () => {
|
||||
const originalError = new Error('I am an error');
|
||||
const statusCode = 404;
|
||||
const wrappedError = wrapCustomError(originalError, statusCode);
|
||||
|
||||
expect(wrappedError.isBoom).to.be(true);
|
||||
expect(wrappedError.output.statusCode).to.equal(statusCode);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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 expect from '@kbn/expect';
|
||||
import { wrapEsError } from '../wrap_es_error';
|
||||
|
||||
describe('wrap_es_error', () => {
|
||||
describe('#wrapEsError', () => {
|
||||
let originalError;
|
||||
beforeEach(() => {
|
||||
originalError = new Error('I am an error');
|
||||
originalError.statusCode = 404;
|
||||
});
|
||||
|
||||
it('should return a Boom object', () => {
|
||||
const wrappedError = wrapEsError(originalError);
|
||||
|
||||
expect(wrappedError.isBoom).to.be(true);
|
||||
});
|
||||
|
||||
it('should return the correct Boom object', () => {
|
||||
const wrappedError = wrapEsError(originalError);
|
||||
|
||||
expect(wrappedError.output.statusCode).to.be(originalError.statusCode);
|
||||
expect(wrappedError.output.payload.message).to.be(originalError.message);
|
||||
});
|
||||
|
||||
it('should return the correct Boom object with custom message', () => {
|
||||
const wrappedError = wrapEsError(originalError, { 404: 'No encontrado!' });
|
||||
|
||||
expect(wrappedError.output.statusCode).to.be(originalError.statusCode);
|
||||
expect(wrappedError.output.payload.message).to.be('No encontrado!');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,19 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { wrapUnknownError } from '../wrap_unknown_error';
|
||||
|
||||
describe('wrap_unknown_error', () => {
|
||||
describe('#wrapUnknownError', () => {
|
||||
it('should return a Boom object', () => {
|
||||
const originalError = new Error('I am an error');
|
||||
const wrappedError = wrapUnknownError(originalError);
|
||||
|
||||
expect(wrappedError.isBoom).to.be(true);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,9 +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 { wrapCustomError } from './wrap_custom_error';
|
||||
export { wrapEsError } from './wrap_es_error';
|
||||
export { wrapUnknownError } from './wrap_unknown_error';
|
|
@ -1,18 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import Boom from 'boom';
|
||||
|
||||
/**
|
||||
* Wraps a custom error into a Boom error response and returns it
|
||||
*
|
||||
* @param err Object error
|
||||
* @param statusCode Error status code
|
||||
* @return Object Boom error response
|
||||
*/
|
||||
export function wrapCustomError(err: any, statusCode: any): any {
|
||||
return Boom.boomify(err, { statusCode });
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import Boom from 'boom';
|
||||
|
||||
/**
|
||||
* Wraps an error thrown by the ES JS client into a Boom error response and returns it
|
||||
*
|
||||
* @param err Object Error thrown by ES JS client
|
||||
* @param statusCodeToMessageMap Object Optional map of HTTP status codes => error messages
|
||||
* @return Object Boom error response
|
||||
*/
|
||||
export function wrapEsError(err: any, statusCodeToMessageMap: any = {}): any {
|
||||
const statusCode = err.statusCode;
|
||||
|
||||
// If no custom message if specified for the error's status code, just
|
||||
// wrap the error as a Boom error response and return it
|
||||
if (!statusCodeToMessageMap[statusCode]) {
|
||||
return Boom.boomify(err, { statusCode });
|
||||
}
|
||||
|
||||
// Otherwise, use the custom message to create a Boom error response and
|
||||
// return it
|
||||
const message = statusCodeToMessageMap[statusCode];
|
||||
return new Boom(message, { statusCode });
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import Boom from 'boom';
|
||||
|
||||
/**
|
||||
* Wraps an unknown error into a Boom error response and returns it
|
||||
*
|
||||
* @param err Object Unknown error
|
||||
* @return Object Boom error response
|
||||
*/
|
||||
export function wrapUnknownError(err: any): any {
|
||||
return Boom.boomify(err);
|
||||
}
|
|
@ -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 { isEsError } from './is_es_error';
|
|
@ -1,69 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { licensePreRoutingFactory } from '../license_pre_routing_factory';
|
||||
|
||||
describe('license_pre_routing_factory', () => {
|
||||
describe('#reportingFeaturePreRoutingFactory', () => {
|
||||
let mockServer;
|
||||
let mockLicenseCheckResults;
|
||||
|
||||
beforeEach(() => {
|
||||
mockServer = {
|
||||
plugins: {
|
||||
xpack_main: {
|
||||
info: {
|
||||
feature: () => ({
|
||||
getLicenseCheckResults: () => mockLicenseCheckResults,
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
it('only instantiates one instance per server', () => {
|
||||
const firstInstance = licensePreRoutingFactory(mockServer);
|
||||
const secondInstance = licensePreRoutingFactory(mockServer);
|
||||
|
||||
expect(firstInstance).to.be(secondInstance);
|
||||
});
|
||||
|
||||
describe('isAvailable is false', () => {
|
||||
beforeEach(() => {
|
||||
mockLicenseCheckResults = {
|
||||
isAvailable: false,
|
||||
};
|
||||
});
|
||||
|
||||
it('replies with 403', () => {
|
||||
const licensePreRouting = licensePreRoutingFactory(mockServer);
|
||||
const stubRequest = {};
|
||||
expect(() => licensePreRouting(stubRequest)).to.throwException(response => {
|
||||
expect(response).to.be.an(Error);
|
||||
expect(response.isBoom).to.be(true);
|
||||
expect(response.output.statusCode).to.be(403);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isAvailable is true', () => {
|
||||
beforeEach(() => {
|
||||
mockLicenseCheckResults = {
|
||||
isAvailable: true,
|
||||
};
|
||||
});
|
||||
|
||||
it('replies with nothing', () => {
|
||||
const licensePreRouting = licensePreRoutingFactory(mockServer);
|
||||
const stubRequest = {};
|
||||
const response = licensePreRouting(stubRequest);
|
||||
expect(response).to.be(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,29 +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 { Legacy } from 'kibana';
|
||||
|
||||
import { PLUGIN } from '../../../common/constants';
|
||||
import { wrapCustomError } from '../error_wrappers';
|
||||
|
||||
export const licensePreRoutingFactory = once((server: Legacy.Server) => {
|
||||
const xpackMainPlugin = server.plugins.xpack_main;
|
||||
|
||||
// License checking and enable/disable logic
|
||||
function licensePreRouting() {
|
||||
const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults();
|
||||
if (!licenseCheckResults.isAvailable) {
|
||||
const error = new Error(licenseCheckResults.message);
|
||||
const statusCode = 403;
|
||||
throw wrapCustomError(error, statusCode);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return licensePreRouting;
|
||||
});
|
|
@ -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';
|
|
@ -1,23 +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 { Legacy } from 'kibana';
|
||||
// @ts-ignore
|
||||
import { mirrorPluginStatus } from '../../../../../server/lib/mirror_plugin_status';
|
||||
import { PLUGIN } from '../../../common/constants';
|
||||
import { checkLicense } from '../check_license';
|
||||
|
||||
export function registerLicenseChecker(server: Legacy.Server) {
|
||||
const xpackMainPlugin = server.plugins.xpack_main as any;
|
||||
const ilmPlugin = (server.plugins as any).index_lifecycle_management;
|
||||
|
||||
mirrorPluginStatus(xpackMainPlugin, ilmPlugin);
|
||||
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);
|
||||
});
|
||||
}
|
|
@ -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 { registerIndexRoutes } from './register_index_routes';
|
|
@ -1,58 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
|
||||
import { isEsError } from '../../../lib/is_es_error';
|
||||
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
|
||||
import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory';
|
||||
|
||||
async function addLifecyclePolicy(
|
||||
callWithRequest: any,
|
||||
indexName: string,
|
||||
policyName: string,
|
||||
alias: string
|
||||
) {
|
||||
const body = {
|
||||
lifecycle: {
|
||||
name: policyName,
|
||||
rollover_alias: alias,
|
||||
},
|
||||
};
|
||||
|
||||
const params = {
|
||||
method: 'PUT',
|
||||
path: `/${encodeURIComponent(indexName)}/_settings`,
|
||||
body,
|
||||
};
|
||||
|
||||
return callWithRequest('transport.request', params);
|
||||
}
|
||||
|
||||
export function registerAddPolicyRoute(server: any) {
|
||||
const licensePreRouting = licensePreRoutingFactory(server);
|
||||
|
||||
server.route({
|
||||
path: '/api/index_lifecycle_management/index/add',
|
||||
method: 'POST',
|
||||
handler: async (request: any) => {
|
||||
const callWithRequest = callWithRequestFactory(server, request);
|
||||
const { indexName, policyName, alias } = request.payload as any;
|
||||
try {
|
||||
const response = await addLifecyclePolicy(callWithRequest, indexName, policyName, alias);
|
||||
return response;
|
||||
} catch (err) {
|
||||
if (isEsError(err)) {
|
||||
return wrapEsError(err);
|
||||
}
|
||||
|
||||
return wrapUnknownError(err);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
pre: [licensePreRouting],
|
||||
},
|
||||
});
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
|
||||
import { isEsError } from '../../../lib/is_es_error';
|
||||
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
|
||||
import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory';
|
||||
|
||||
async function removeLifecycle(callWithRequest: any, indexNames: string[]) {
|
||||
const responses = [];
|
||||
for (let i = 0; i < indexNames.length; i++) {
|
||||
const indexName = indexNames[i];
|
||||
const params = {
|
||||
method: 'POST',
|
||||
path: `/${encodeURIComponent(indexName)}/_ilm/remove`,
|
||||
ignore: [404],
|
||||
};
|
||||
|
||||
responses.push(callWithRequest('transport.request', params));
|
||||
}
|
||||
return Promise.all(responses);
|
||||
}
|
||||
|
||||
export function registerRemoveRoute(server: any) {
|
||||
const licensePreRouting = licensePreRoutingFactory(server);
|
||||
|
||||
server.route({
|
||||
path: '/api/index_lifecycle_management/index/remove',
|
||||
method: 'POST',
|
||||
handler: async (request: any) => {
|
||||
const callWithRequest = callWithRequestFactory(server, request);
|
||||
|
||||
try {
|
||||
const response = await removeLifecycle(callWithRequest, request.payload.indexNames);
|
||||
return response;
|
||||
} catch (err) {
|
||||
if (isEsError(err)) {
|
||||
return wrapEsError(err);
|
||||
}
|
||||
|
||||
return wrapUnknownError(err);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
pre: [licensePreRouting],
|
||||
},
|
||||
});
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
|
||||
import { isEsError } from '../../../lib/is_es_error';
|
||||
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
|
||||
import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory';
|
||||
|
||||
async function retryLifecycle(callWithRequest: any, indexNames: string[]) {
|
||||
const responses = [];
|
||||
for (let i = 0; i < indexNames.length; i++) {
|
||||
const indexName = indexNames[i];
|
||||
const params = {
|
||||
method: 'POST',
|
||||
path: `/${encodeURIComponent(indexName)}/_ilm/retry`,
|
||||
ignore: [404],
|
||||
};
|
||||
|
||||
responses.push(callWithRequest('transport.request', params));
|
||||
}
|
||||
return Promise.all(responses);
|
||||
}
|
||||
|
||||
export function registerRetryRoute(server: any) {
|
||||
const licensePreRouting = licensePreRoutingFactory(server);
|
||||
|
||||
server.route({
|
||||
path: '/api/index_lifecycle_management/index/retry',
|
||||
method: 'POST',
|
||||
handler: async (request: any) => {
|
||||
const callWithRequest = callWithRequestFactory(server, request);
|
||||
|
||||
try {
|
||||
const response = await retryLifecycle(callWithRequest, request.payload.indexNames);
|
||||
return response;
|
||||
} catch (err) {
|
||||
if (isEsError(err)) {
|
||||
return wrapEsError(err);
|
||||
}
|
||||
|
||||
return wrapUnknownError(err);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
pre: [licensePreRouting],
|
||||
},
|
||||
});
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export const NODE_ATTRS_KEYS_TO_IGNORE: string[] = [
|
||||
'ml.enabled',
|
||||
'ml.machine_memory',
|
||||
'ml.max_open_jobs',
|
||||
// Used by ML to identify nodes that have transform enabled:
|
||||
// https://github.com/elastic/elasticsearch/pull/52712/files#diff-225cc2c1291b4c60a8c3412a619094e1R147
|
||||
'transform.node',
|
||||
'xpack.installed',
|
||||
];
|
|
@ -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 { registerNodesRoutes } from './register_nodes_routes';
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
|
||||
import { isEsError } from '../../../lib/is_es_error';
|
||||
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
|
||||
import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory';
|
||||
|
||||
function findMatchingNodes(stats: any, nodeAttrs: string): any {
|
||||
return Object.entries(stats.nodes).reduce((accum: any[], [nodeId, nodeStats]: [any, any]) => {
|
||||
const attributes = nodeStats.attributes || {};
|
||||
for (const [key, value] of Object.entries(attributes)) {
|
||||
if (`${key}:${value}` === nodeAttrs) {
|
||||
accum.push({
|
||||
nodeId,
|
||||
stats: nodeStats,
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
return accum;
|
||||
}, []);
|
||||
}
|
||||
|
||||
async function fetchNodeStats(callWithRequest: any): Promise<any> {
|
||||
const params = {
|
||||
format: 'json',
|
||||
};
|
||||
|
||||
return await callWithRequest('nodes.stats', params);
|
||||
}
|
||||
|
||||
export function registerDetailsRoute(server: any) {
|
||||
const licensePreRouting = licensePreRoutingFactory(server);
|
||||
|
||||
server.route({
|
||||
path: '/api/index_lifecycle_management/nodes/{nodeAttrs}/details',
|
||||
method: 'GET',
|
||||
handler: async (request: any) => {
|
||||
const callWithRequest = callWithRequestFactory(server, request);
|
||||
|
||||
try {
|
||||
const stats = await fetchNodeStats(callWithRequest);
|
||||
const response = findMatchingNodes(stats, request.params.nodeAttrs);
|
||||
return response;
|
||||
} catch (err) {
|
||||
if (isEsError(err)) {
|
||||
return wrapEsError(err);
|
||||
}
|
||||
|
||||
return wrapUnknownError(err);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
pre: [licensePreRouting],
|
||||
},
|
||||
});
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
|
||||
import { isEsError } from '../../../lib/is_es_error';
|
||||
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
|
||||
import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory';
|
||||
import { NODE_ATTRS_KEYS_TO_IGNORE } from './constants';
|
||||
|
||||
function convertStatsIntoList(stats: any, attributesToBeFiltered: string[]): any {
|
||||
return Object.entries(stats.nodes).reduce((accum: any, [nodeId, nodeStats]: [any, any]) => {
|
||||
const attributes = nodeStats.attributes || {};
|
||||
for (const [key, value] of Object.entries(attributes)) {
|
||||
if (!attributesToBeFiltered.includes(key)) {
|
||||
const attributeString = `${key}:${value}`;
|
||||
accum[attributeString] = accum[attributeString] || [];
|
||||
accum[attributeString].push(nodeId);
|
||||
}
|
||||
}
|
||||
return accum;
|
||||
}, {});
|
||||
}
|
||||
|
||||
async function fetchNodeStats(callWithRequest: any): Promise<any> {
|
||||
const params = {
|
||||
format: 'json',
|
||||
};
|
||||
|
||||
return await callWithRequest('nodes.stats', params);
|
||||
}
|
||||
|
||||
export function registerListRoute(server: any) {
|
||||
const config = server.config();
|
||||
const filteredNodeAttributes = config.get('xpack.ilm.filteredNodeAttributes');
|
||||
const attributesToBeFiltered = [...NODE_ATTRS_KEYS_TO_IGNORE, ...filteredNodeAttributes];
|
||||
const licensePreRouting = licensePreRoutingFactory(server);
|
||||
|
||||
server.route({
|
||||
path: '/api/index_lifecycle_management/nodes/list',
|
||||
method: 'GET',
|
||||
handler: async (request: any) => {
|
||||
const callWithRequest = callWithRequestFactory(server, request);
|
||||
|
||||
try {
|
||||
const stats = await fetchNodeStats(callWithRequest);
|
||||
const response = convertStatsIntoList(stats, attributesToBeFiltered);
|
||||
return response;
|
||||
} catch (err) {
|
||||
if (isEsError(err)) {
|
||||
return wrapEsError(err);
|
||||
}
|
||||
|
||||
return wrapUnknownError(err);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
pre: [licensePreRouting],
|
||||
},
|
||||
});
|
||||
}
|
|
@ -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 { registerPoliciesRoutes } from './register_policies_routes';
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
|
||||
import { isEsError } from '../../../lib/is_es_error';
|
||||
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
|
||||
import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory';
|
||||
|
||||
async function createPolicy(callWithRequest: any, policy: any): Promise<any> {
|
||||
const body = {
|
||||
policy: {
|
||||
phases: policy.phases,
|
||||
},
|
||||
};
|
||||
const params = {
|
||||
method: 'PUT',
|
||||
path: `/_ilm/policy/${encodeURIComponent(policy.name)}`,
|
||||
ignore: [404],
|
||||
body,
|
||||
};
|
||||
|
||||
return await callWithRequest('transport.request', params);
|
||||
}
|
||||
|
||||
export function registerCreateRoute(server: any) {
|
||||
const licensePreRouting = licensePreRoutingFactory(server);
|
||||
|
||||
server.route({
|
||||
path: '/api/index_lifecycle_management/policies',
|
||||
method: 'POST',
|
||||
handler: async (request: any) => {
|
||||
const callWithRequest = callWithRequestFactory(server, request);
|
||||
|
||||
try {
|
||||
const response = await createPolicy(callWithRequest, request.payload);
|
||||
return response;
|
||||
} catch (err) {
|
||||
if (isEsError(err)) {
|
||||
return wrapEsError(err);
|
||||
}
|
||||
|
||||
return wrapUnknownError(err);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
pre: [licensePreRouting],
|
||||
},
|
||||
});
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
|
||||
import { isEsError } from '../../../lib/is_es_error';
|
||||
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
|
||||
import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory';
|
||||
|
||||
async function deletePolicies(policyNames: string, callWithRequest: any): Promise<any> {
|
||||
const params = {
|
||||
method: 'DELETE',
|
||||
path: `/_ilm/policy/${encodeURIComponent(policyNames)}`,
|
||||
// we allow 404 since they may have no policies
|
||||
ignore: [404],
|
||||
};
|
||||
|
||||
return await callWithRequest('transport.request', params);
|
||||
}
|
||||
|
||||
export function registerDeleteRoute(server: any) {
|
||||
const licensePreRouting = licensePreRoutingFactory(server);
|
||||
|
||||
server.route({
|
||||
path: '/api/index_lifecycle_management/policies/{policyNames}',
|
||||
method: 'DELETE',
|
||||
handler: async (request: any) => {
|
||||
const callWithRequest = callWithRequestFactory(server, request);
|
||||
const { policyNames } = request.params;
|
||||
try {
|
||||
await deletePolicies(policyNames, callWithRequest);
|
||||
return {};
|
||||
} catch (err) {
|
||||
if (isEsError(err)) {
|
||||
return wrapEsError(err);
|
||||
}
|
||||
return wrapUnknownError(err);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
pre: [licensePreRouting],
|
||||
},
|
||||
});
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
|
||||
import { isEsError } from '../../../lib/is_es_error';
|
||||
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
|
||||
import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory';
|
||||
|
||||
function formatPolicies(policiesMap: any): any {
|
||||
if (policiesMap.status === 404) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Object.keys(policiesMap).reduce((accum: any[], lifecycleName: string) => {
|
||||
const policyEntry = policiesMap[lifecycleName];
|
||||
accum.push({
|
||||
...policyEntry,
|
||||
name: lifecycleName,
|
||||
});
|
||||
return accum;
|
||||
}, []);
|
||||
}
|
||||
|
||||
async function fetchPolicies(callWithRequest: any): Promise<any> {
|
||||
const params = {
|
||||
method: 'GET',
|
||||
path: '/_ilm/policy',
|
||||
// we allow 404 since they may have no policies
|
||||
ignore: [404],
|
||||
};
|
||||
|
||||
return await callWithRequest('transport.request', params);
|
||||
}
|
||||
async function addLinkedIndices(policiesMap: any, callWithRequest: any) {
|
||||
if (policiesMap.status === 404) {
|
||||
return policiesMap;
|
||||
}
|
||||
const params = {
|
||||
method: 'GET',
|
||||
path: '/*/_ilm/explain',
|
||||
// we allow 404 since they may have no policies
|
||||
ignore: [404],
|
||||
};
|
||||
|
||||
const policyExplanation: any = await callWithRequest('transport.request', params);
|
||||
Object.entries(policyExplanation.indices).forEach(([indexName, { policy }]: [string, any]) => {
|
||||
if (policy && policiesMap[policy]) {
|
||||
policiesMap[policy].linkedIndices = policiesMap[policy].linkedIndices || [];
|
||||
policiesMap[policy].linkedIndices.push(indexName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function registerFetchRoute(server: any) {
|
||||
const licensePreRouting = licensePreRoutingFactory(server);
|
||||
|
||||
server.route({
|
||||
path: '/api/index_lifecycle_management/policies',
|
||||
method: 'GET',
|
||||
handler: async (request: any) => {
|
||||
const callWithRequest = callWithRequestFactory(server, request);
|
||||
const { withIndices } = request.query;
|
||||
try {
|
||||
const policiesMap = await fetchPolicies(callWithRequest);
|
||||
if (withIndices) {
|
||||
await addLinkedIndices(policiesMap, callWithRequest);
|
||||
}
|
||||
return formatPolicies(policiesMap);
|
||||
} catch (err) {
|
||||
if (isEsError(err)) {
|
||||
return wrapEsError(err);
|
||||
}
|
||||
|
||||
return wrapUnknownError(err);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
pre: [licensePreRouting],
|
||||
},
|
||||
});
|
||||
}
|
|
@ -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 { registerTemplatesRoutes } from './register_templates_routes';
|
|
@ -1,67 +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 { merge } from 'lodash';
|
||||
|
||||
import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
|
||||
import { isEsError } from '../../../lib/is_es_error';
|
||||
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
|
||||
import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory';
|
||||
|
||||
async function getIndexTemplate(callWithRequest: any, templateName: string): Promise<any> {
|
||||
const response = await callWithRequest('indices.getTemplate', { name: templateName });
|
||||
return response[templateName];
|
||||
}
|
||||
|
||||
async function updateIndexTemplate(callWithRequest: any, indexTemplatePatch: any): Promise<any> {
|
||||
// Fetch existing template
|
||||
const template = await getIndexTemplate(callWithRequest, indexTemplatePatch.templateName);
|
||||
merge(template, {
|
||||
settings: {
|
||||
index: {
|
||||
lifecycle: {
|
||||
name: indexTemplatePatch.policyName,
|
||||
rollover_alias: indexTemplatePatch.aliasName,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const params = {
|
||||
method: 'PUT',
|
||||
path: `/_template/${encodeURIComponent(indexTemplatePatch.templateName)}`,
|
||||
ignore: [404],
|
||||
body: template,
|
||||
};
|
||||
|
||||
return await callWithRequest('transport.request', params);
|
||||
}
|
||||
|
||||
export function registerAddPolicyRoute(server: any) {
|
||||
const licensePreRouting = licensePreRoutingFactory(server);
|
||||
|
||||
server.route({
|
||||
path: '/api/index_lifecycle_management/template',
|
||||
method: 'POST',
|
||||
handler: async (request: any) => {
|
||||
const callWithRequest = callWithRequestFactory(server, request);
|
||||
|
||||
try {
|
||||
const response = await updateIndexTemplate(callWithRequest, request.payload);
|
||||
return response;
|
||||
} catch (err) {
|
||||
if (isEsError(err)) {
|
||||
return wrapEsError(err);
|
||||
}
|
||||
|
||||
return wrapUnknownError(err);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
pre: [licensePreRouting],
|
||||
},
|
||||
});
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
|
||||
import { isEsError } from '../../../lib/is_es_error';
|
||||
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
|
||||
import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory';
|
||||
|
||||
async function fetchTemplate(callWithRequest: any, templateName: string): Promise<any> {
|
||||
const params = {
|
||||
method: 'GET',
|
||||
path: `/_template/${encodeURIComponent(templateName)}`,
|
||||
// we allow 404 incase the user shutdown security in-between the check and now
|
||||
ignore: [404],
|
||||
};
|
||||
|
||||
return await callWithRequest('transport.request', params);
|
||||
}
|
||||
|
||||
export function registerGetRoute(server: any) {
|
||||
const licensePreRouting = licensePreRoutingFactory(server);
|
||||
|
||||
server.route({
|
||||
path: '/api/index_lifecycle_management/templates/{templateName}',
|
||||
method: 'GET',
|
||||
handler: async (request: any) => {
|
||||
const callWithRequest = callWithRequestFactory(server, request);
|
||||
const templateName = request.params.templateName;
|
||||
|
||||
try {
|
||||
const template = await fetchTemplate(callWithRequest, templateName);
|
||||
return template[templateName];
|
||||
} catch (err) {
|
||||
if (isEsError(err)) {
|
||||
return wrapEsError(err);
|
||||
}
|
||||
|
||||
return wrapUnknownError(err);
|
||||
}
|
||||
},
|
||||
config: {
|
||||
pre: [licensePreRouting],
|
||||
},
|
||||
});
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { Legacy } from 'kibana';
|
||||
|
||||
export interface LegacySetup {
|
||||
server: Legacy.Server;
|
||||
}
|
||||
|
||||
export function createShim(server: Legacy.Server): LegacySetup {
|
||||
return {
|
||||
server,
|
||||
};
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
// TODO: Remove this once CCR is migrated to the plugins directory.
|
||||
export function indexManagement(kibana: any) {
|
||||
return new kibana.Plugin({
|
||||
id: 'index_management',
|
||||
|
|
|
@ -24,7 +24,7 @@ import {
|
|||
// @ts-ignore
|
||||
import { CRUD_APP_BASE_PATH } from './crud_app/constants';
|
||||
import { ManagementSetup } from '../../../../../src/plugins/management/public';
|
||||
import { IndexMgmtSetup } from '../../../../plugins/index_management/public';
|
||||
import { IndexManagementPluginSetup } from '../../../../plugins/index_management/public';
|
||||
import { IndexPatternManagementSetup } from '../../../../../src/plugins/index_pattern_management/public';
|
||||
import { search } from '../../../../../src/plugins/data/public';
|
||||
// @ts-ignore
|
||||
|
@ -35,7 +35,7 @@ import { renderApp } from './application';
|
|||
export interface RollupPluginSetupDependencies {
|
||||
home?: HomePublicPluginSetup;
|
||||
management: ManagementSetup;
|
||||
indexManagement?: IndexMgmtSetup;
|
||||
indexManagement?: IndexManagementPluginSetup;
|
||||
indexPatternManagement: IndexPatternManagementSetup;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import { i18n } from '@kbn/i18n';
|
|||
|
||||
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
|
||||
import { VisTypeTimeseriesSetup } from 'src/plugins/vis_type_timeseries/server';
|
||||
import { IndexMgmtSetup } from '../../../../plugins/index_management/server';
|
||||
import { IndexManagementPluginSetup } from '../../../../plugins/index_management/server';
|
||||
import { registerLicenseChecker } from '../../../server/lib/register_license_checker';
|
||||
import { PLUGIN } from '../common';
|
||||
import { ServerShim, RouteDependencies } from './types';
|
||||
|
@ -44,7 +44,7 @@ export class RollupsServerPlugin implements Plugin<void, void, any, any> {
|
|||
__LEGACY: ServerShim;
|
||||
usageCollection?: UsageCollectionSetup;
|
||||
metrics?: VisTypeTimeseriesSetup;
|
||||
indexManagement?: IndexMgmtSetup;
|
||||
indexManagement?: IndexManagementPluginSetup;
|
||||
}
|
||||
) {
|
||||
const elasticsearch = await elasticsearchService.adminClient;
|
||||
|
|
|
@ -13,13 +13,13 @@ import axiosXhrAdapter from 'axios/lib/adapters/xhr';
|
|||
import sinon from 'sinon';
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
|
||||
import { mountWithIntl } from '../../../../../test_utils/enzyme_helpers';
|
||||
import { fetchedPolicies, fetchedNodes } from '../../public/np_ready/application/store/actions';
|
||||
import { indexLifecycleManagementStore } from '../../public/np_ready/application/store';
|
||||
import { EditPolicy } from '../../public/np_ready/application/sections/edit_policy';
|
||||
import { init as initHttp } from '../../public/np_ready/application/services/http';
|
||||
import { init as initUiMetric } from '../../public/np_ready/application/services/ui_metric';
|
||||
import { init as initNotification } from '../../public/np_ready/application/services/notification';
|
||||
import { mountWithIntl } from '../../../../test_utils/enzyme_helpers';
|
||||
import { fetchedPolicies, fetchedNodes } from '../../public/application/store/actions';
|
||||
import { indexLifecycleManagementStore } from '../../public/application/store';
|
||||
import { EditPolicy } from '../../public/application/sections/edit_policy';
|
||||
import { init as initHttp } from '../../public/application/services/http';
|
||||
import { init as initUiMetric } from '../../public/application/services/ui_metric';
|
||||
import { init as initNotification } from '../../public/application/services/notification';
|
||||
import {
|
||||
positiveNumbersAboveZeroErrorMessage,
|
||||
positiveNumberRequiredMessage,
|
||||
|
@ -33,16 +33,14 @@ import {
|
|||
policyNameMustBeDifferentErrorMessage,
|
||||
policyNameAlreadyUsedErrorMessage,
|
||||
maximumDocumentsRequiredMessage,
|
||||
} from '../../public/np_ready/application/store/selectors/lifecycle';
|
||||
} from '../../public/application/store/selectors/lifecycle';
|
||||
|
||||
initHttp(axios.create({ adapter: axiosXhrAdapter }), path => path);
|
||||
initUiMetric(() => () => {});
|
||||
initUiMetric({ reportUiStats: () => {} });
|
||||
initNotification({
|
||||
addDanger: () => {},
|
||||
});
|
||||
|
||||
jest.mock('ui/new_platform');
|
||||
|
||||
let server;
|
||||
let store;
|
||||
const policy = {
|
|
@ -12,17 +12,15 @@ import axiosXhrAdapter from 'axios/lib/adapters/xhr';
|
|||
import sinon from 'sinon';
|
||||
import { findTestSubject, takeMountedSnapshot } from '@elastic/eui/lib/test';
|
||||
|
||||
import { mountWithIntl } from '../../../../../test_utils/enzyme_helpers';
|
||||
import { fetchedPolicies } from '../../public/np_ready/application/store/actions';
|
||||
import { indexLifecycleManagementStore } from '../../public/np_ready/application/store';
|
||||
import { PolicyTable } from '../../public/np_ready/application/sections/policy_table';
|
||||
import { init as initHttp } from '../../public/np_ready/application/services/http';
|
||||
import { init as initUiMetric } from '../../public/np_ready/application/services/ui_metric';
|
||||
import { mountWithIntl } from '../../../../test_utils/enzyme_helpers';
|
||||
import { fetchedPolicies } from '../../public/application/store/actions';
|
||||
import { indexLifecycleManagementStore } from '../../public/application/store';
|
||||
import { PolicyTable } from '../../public/application/sections/policy_table';
|
||||
import { init as initHttp } from '../../public/application/services/http';
|
||||
import { init as initUiMetric } from '../../public/application/services/ui_metric';
|
||||
|
||||
initHttp(axios.create({ adapter: axiosXhrAdapter }), path => path);
|
||||
initUiMetric(() => () => {});
|
||||
|
||||
jest.mock('ui/new_platform');
|
||||
initUiMetric({ reportUiStats: () => {} });
|
||||
|
||||
let server = null;
|
||||
|
|
@ -8,7 +8,7 @@ import moment from 'moment-timezone';
|
|||
import axios from 'axios';
|
||||
import axiosXhrAdapter from 'axios/lib/adapters/xhr';
|
||||
|
||||
import { mountWithIntl } from '../../../../test_utils/enzyme_helpers';
|
||||
import { mountWithIntl } from '../../../test_utils/enzyme_helpers';
|
||||
import {
|
||||
retryLifecycleActionExtension,
|
||||
removeLifecyclePolicyActionExtension,
|
||||
|
@ -16,21 +16,18 @@ import {
|
|||
ilmBannerExtension,
|
||||
ilmFilterExtension,
|
||||
ilmSummaryExtension,
|
||||
} from '../public/np_ready/extend_index_management';
|
||||
import { init as initHttp } from '../public/np_ready/application/services/http';
|
||||
import { init as initUiMetric } from '../public/np_ready/application/services/ui_metric';
|
||||
} from '../public/extend_index_management';
|
||||
import { init as initHttp } from '../public/application/services/http';
|
||||
import { init as initUiMetric } from '../public/application/services/ui_metric';
|
||||
|
||||
// We need to init the http with a mock for any tests that depend upon the http service.
|
||||
// For example, add_lifecycle_confirm_modal makes an API request in its componentDidMount
|
||||
// lifecycle method. If we don't mock this, CI will fail with "Call retries were exceeded".
|
||||
initHttp(axios.create({ adapter: axiosXhrAdapter }), path => path);
|
||||
initUiMetric(() => () => {});
|
||||
initUiMetric({ reportUiStats: () => {} });
|
||||
|
||||
jest.mock('ui/new_platform');
|
||||
jest.mock('../../../../plugins/index_management/public', async () => {
|
||||
const { indexManagementMock } = await import(
|
||||
'../../../../plugins/index_management/public/mocks.ts'
|
||||
);
|
||||
jest.mock('../../../plugins/index_management/public', async () => {
|
||||
const { indexManagementMock } = await import('../../../plugins/index_management/public/mocks.ts');
|
||||
return indexManagementMock.createSetup();
|
||||
});
|
||||
|
|
@ -5,12 +5,18 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { LicenseType } from '../../../licensing/common/types';
|
||||
|
||||
const basicLicense: LicenseType = 'basic';
|
||||
|
||||
export const PLUGIN = {
|
||||
ID: 'index_lifecycle_management',
|
||||
minimumLicenseType: basicLicense,
|
||||
TITLE: i18n.translate('xpack.indexLifecycleMgmt.appTitle', {
|
||||
defaultMessage: 'Index Lifecycle Policies',
|
||||
}),
|
||||
};
|
||||
|
||||
export const BASE_PATH = '/management/elasticsearch/index_lifecycle_management/';
|
||||
|
||||
export const API_BASE_PATH = '/api/index_lifecycle_management';
|
16
x-pack/plugins/index_lifecycle_management/kibana.json
Normal file
16
x-pack/plugins/index_lifecycle_management/kibana.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"id": "indexLifecycleManagement",
|
||||
"version": "kibana",
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": [
|
||||
"home",
|
||||
"licensing",
|
||||
"management"
|
||||
],
|
||||
"optionalPlugins": [
|
||||
"usageCollection",
|
||||
"indexManagement"
|
||||
],
|
||||
"configPath": ["xpack", "ilm"]
|
||||
}
|
|
@ -8,7 +8,7 @@ import React, { useEffect } from 'react';
|
|||
import { HashRouter, Switch, Route, Redirect } from 'react-router-dom';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
|
||||
import { BASE_PATH } from '../../../common/constants';
|
||||
import { BASE_PATH } from '../../common/constants';
|
||||
import { UIM_APP_LOAD } from './constants';
|
||||
import { EditPolicy } from './sections/edit_policy';
|
||||
import { PolicyTable } from './sections/policy_table';
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import { I18nStart } from 'kibana/public';
|
||||
import { UnmountCallback } from 'src/core/public';
|
||||
|
||||
import { App } from './app';
|
||||
import { indexLifecycleManagementStore } from './store';
|
||||
|
||||
export const renderApp = (element: Element, I18nContext: I18nStart['Context']): UnmountCallback => {
|
||||
render(
|
||||
<I18nContext>
|
||||
<Provider store={indexLifecycleManagementStore()}>
|
||||
<App />
|
||||
</Provider>
|
||||
</I18nContext>,
|
||||
element
|
||||
);
|
||||
|
||||
return () => unmountComponentAtNode(element);
|
||||
};
|
|
@ -37,8 +37,8 @@ import {
|
|||
|
||||
import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services';
|
||||
|
||||
import { getIndexListUri } from '../../../../../../../../../../plugins/index_management/public';
|
||||
import { BASE_PATH } from '../../../../../../../common/constants';
|
||||
import { getIndexListUri } from '../../../../../../../index_management/public';
|
||||
import { BASE_PATH } from '../../../../../../common/constants';
|
||||
import { UIM_EDIT_CLICK } from '../../../../constants';
|
||||
import { getPolicyPath } from '../../../../services/navigation';
|
||||
import { flattenPanelTree } from '../../../../services/flatten_panel_tree';
|
||||
|
@ -52,6 +52,7 @@ const COLUMNS = {
|
|||
label: i18n.translate('xpack.indexLifecycleMgmt.policyTable.headers.nameHeader', {
|
||||
defaultMessage: 'Name',
|
||||
}),
|
||||
width: 200,
|
||||
},
|
||||
linkedIndices: {
|
||||
label: i18n.translate('xpack.indexLifecycleMgmt.policyTable.headers.linkedIndicesHeader', {
|
||||
|
@ -179,7 +180,6 @@ export class PolicyTable extends Component {
|
|||
return (
|
||||
/* eslint-disable-next-line @elastic/eui/href-or-on-click */
|
||||
<EuiLink
|
||||
className="policyTable__link"
|
||||
data-test-subj="policyTablePolicyNameLink"
|
||||
href={getPolicyPath(value)}
|
||||
onClick={() => trackUiMetric('click', UIM_EDIT_CLICK)}
|
||||
|
@ -415,7 +415,7 @@ export class PolicyTable extends Component {
|
|||
tableContent = <EuiLoadingSpinner size="m" />;
|
||||
} else if (totalNumberOfPolicies > 0) {
|
||||
tableContent = (
|
||||
<EuiTable className="policyTable__horizontalScroll">
|
||||
<EuiTable>
|
||||
<EuiScreenReaderOnly>
|
||||
<caption role="status" aria-relevant="text" aria-live="polite">
|
||||
<FormattedMessage
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue