From 1b421cc2baa6e85e160f5b497add2dd4e6245796 Mon Sep 17 00:00:00 2001
From: Chris Roberson
Date: Fri, 27 Apr 2018 09:16:48 -0400
Subject: [PATCH 001/102] Index lifecycle management wizard
---
package.json | 1 +
x-pack/index.js | 2 ++
yarn.lock | 17 ++++++++++++++---
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/package.json b/package.json
index 231f032931205..da31a96649502 100644
--- a/package.json
+++ b/package.json
@@ -166,6 +166,7 @@
"querystring-browser": "1.0.4",
"raw-loader": "0.5.1",
"react": "^16.2.0",
+ "react-ace": "6.0.0",
"react-addons-shallow-compare": "15.6.2",
"react-anything-sortable": "^1.7.4",
"react-color": "^2.13.8",
diff --git a/x-pack/index.js b/x-pack/index.js
index ba26c8fcf4161..0b55fde48ecd2 100644
--- a/x-pack/index.js
+++ b/x-pack/index.js
@@ -20,6 +20,7 @@ import { apm } from './plugins/apm';
import { licenseManagement } from './plugins/license_management';
import { cloud } from './plugins/cloud';
import { indexManagement } from './plugins/index_management';
+import { indexLifecycleManagement } from './plugins/index_lifecycle_management';
import { consoleExtensions } from './plugins/console_extensions';
module.exports = function (kibana) {
@@ -40,6 +41,7 @@ module.exports = function (kibana) {
licenseManagement(kibana),
cloud(kibana),
indexManagement(kibana),
+ indexLifecycleManagement(kibana),
consoleExtensions(kibana)
];
};
diff --git a/yarn.lock b/yarn.lock
index 30b183fc31286..c77b70093e420 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3589,6 +3589,10 @@ di@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
+diff-match-patch@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.0.tgz#1cc3c83a490d67f95d91e39f6ad1f2e086b63048"
+
diff@3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
@@ -10220,6 +10224,16 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
+react-ace@6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-6.0.0.tgz#c211c21825f27343a7392f102493dc3ae099886d"
+ dependencies:
+ brace "^0.11.0"
+ diff-match-patch "^1.0.0"
+ lodash.get "^4.4.2"
+ lodash.isequal "^4.1.1"
+ prop-types "^15.5.8"
+
react-ace@^5.5.0, react-ace@^5.9.0:
version "5.9.0"
resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-5.9.0.tgz#427a1cc4869b960a6f9748aa7eb169a9269fc336"
@@ -10683,9 +10697,6 @@ regex-cache@^0.4.2:
regex-not@^1.0.0, regex-not@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c"
- dependencies:
- extend-shallow "^3.0.2"
- safe-regex "^1.1.0"
regexpu-core@^1.0.0:
version "1.0.0"
From eb7fc0fb1a538cd228cf78e2403e13b65e977906 Mon Sep 17 00:00:00 2001
From: Chris Roberson
Date: Fri, 27 Apr 2018 09:41:54 -0400
Subject: [PATCH 002/102] Adding index lifecycle management files
---
package.json | 1 -
x-pack/package.json | 1 +
.../index_lifecycle_management/TODO.md | 6 +
.../common/constants/base_path.js | 7 +
.../common/constants/index.js | 8 +
.../common/constants/plugin.js | 9 +
.../index_lifecycle_management/index.js | 38 ++
.../public/api/index.js | 47 +++
.../index_lifecycle_management/public/app.js | 15 +
.../public/index.js | 8 +
.../public/lib/find_errors.js | 19 +
.../public/lib/manage_angular_lifecycle.js | 23 ++
.../public/main.html | 3 +
.../public/register_management_section.js | 17 +
.../public/register_routes.js | 44 +++
.../public/sections/landing/index.js | 10 +
.../sections/landing/landing.container.js | 24 ++
.../public/sections/landing/landing.js | 43 +++
.../configuration/configuration.container.js | 41 ++
.../components/configuration/configuration.js | 156 ++++++++
.../components/configuration/index.js | 7 +
.../components/template_selection/index.js | 7 +
.../template_selection.container.js | 27 ++
.../template_selection/template_selection.js | 85 +++++
.../wizard/components/index_template/index.js | 10 +
.../index_template/index_template.js | 85 +++++
.../cold_phase/cold_phase.container.js | 34 ++
.../components/cold_phase/cold_phase.js | 223 +++++++++++
.../components/cold_phase/index.js | 7 +
.../delete_phase/delete_phase.container.js | 20 +
.../components/delete_phase/delete_phase.js | 155 ++++++++
.../components/delete_phase/index.js | 7 +
.../hot_phase/hot_phase.container.js | 23 ++
.../components/hot_phase/hot_phase.js | 238 ++++++++++++
.../components/hot_phase/index.js | 7 +
.../components/warm_phase/index.js | 7 +
.../warm_phase/warm_phase.container.js | 33 ++
.../components/warm_phase/warm_phase.js | 358 ++++++++++++++++++
.../components/policy_configuration/index.js | 7 +
.../policy_configuration.container.js | 48 +++
.../policy_configuration.js | 254 +++++++++++++
.../components/policy_selection/index.js | 7 +
.../policy_selection.container.js | 29 ++
.../policy_selection/policy_selection.js | 117 ++++++
.../wizard/components/review/index.js | 7 +
.../components/review/review.container.js | 45 +++
.../wizard/components/review/review.js | 177 +++++++++
.../wizard/components/review/review.less | 5 +
.../public/sections/wizard/form_errors.js | 36 ++
.../public/sections/wizard/index.js | 7 +
.../sections/wizard/wizard.container.js | 32 ++
.../public/sections/wizard/wizard.js | 165 ++++++++
.../public/store/actions/general.js | 14 +
.../public/store/actions/index.js | 14 +
.../public/store/actions/index_template.js | 103 +++++
.../public/store/actions/lifecycle.js | 25 ++
.../public/store/actions/nodes.js | 25 ++
.../public/store/actions/policies.js | 31 ++
.../public/store/constants.js | 104 +++++
.../public/store/index.js | 7 +
.../public/store/reducers/general.js | 38 ++
.../public/store/reducers/index.js | 21 +
.../public/store/reducers/index_template.js | 54 +++
.../public/store/reducers/nodes.js | 61 +++
.../public/store/reducers/policies.js | 173 +++++++++
.../public/store/selectors/general.js | 12 +
.../public/store/selectors/index.js | 14 +
.../public/store/selectors/index_template.js | 170 +++++++++
.../public/store/selectors/lifecycle.js | 200 ++++++++++
.../public/store/selectors/nodes.js | 46 +++
.../public/store/selectors/policies.js | 232 ++++++++++++
.../public/store/store.js | 21 +
.../call_with_request_factory.js | 18 +
.../lib/call_with_request_factory/index.js | 7 +
.../check_license/__tests__/check_license.js | 146 +++++++
.../server/lib/check_license/check_license.js | 58 +++
.../server/lib/check_license/index.js | 7 +
.../__tests__/wrap_custom_error.js | 21 +
.../error_wrappers/__tests__/wrap_es_error.js | 39 ++
.../__tests__/wrap_unknown_error.js | 19 +
.../server/lib/error_wrappers/index.js | 9 +
.../lib/error_wrappers/wrap_custom_error.js | 18 +
.../lib/error_wrappers/wrap_es_error.js | 30 ++
.../lib/error_wrappers/wrap_unknown_error.js | 17 +
.../__tests__/is_es_error_factory.js | 48 +++
.../server/lib/is_es_error_factory/index.js | 7 +
.../is_es_error_factory.js | 18 +
.../__tests__/license_pre_routing_factory.js | 72 ++++
.../lib/license_pre_routing_factory/index.js | 7 +
.../license_pre_routing_factory.js | 29 ++
.../lib/register_license_checker/index.js | 7 +
.../register_license_checker.js | 21 +
.../server/routes/api/indices/index.js | 7 +
.../api/indices/register_bootstrap_route.js | 49 +++
.../indices/register_get_affected_route.js | 93 +++++
.../api/indices/register_indices_routes.js | 13 +
.../server/routes/api/lifecycle/index.js | 7 +
.../api/lifecycle/register_create_route.js | 95 +++++
.../lifecycle/register_lifecycle_routes.js | 11 +
.../server/routes/api/nodes/index.js | 7 +
.../routes/api/nodes/register_list_route.js | 61 +++
.../routes/api/nodes/register_nodes_routes.js | 11 +
.../server/routes/api/policies/index.js | 7 +
.../api/policies/register_fetch_route.js | 60 +++
.../api/policies/register_policies_routes.js | 11 +
.../server/routes/api/templates/index.js | 7 +
.../api/templates/register_fetch_route.js | 81 ++++
.../api/templates/register_get_route.js | 52 +++
.../templates/register_templates_routes.js | 16 +
x-pack/yarn.lock | 14 +
110 files changed, 5353 insertions(+), 1 deletion(-)
create mode 100644 x-pack/plugins/index_lifecycle_management/TODO.md
create mode 100644 x-pack/plugins/index_lifecycle_management/common/constants/base_path.js
create mode 100644 x-pack/plugins/index_lifecycle_management/common/constants/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/common/constants/plugin.js
create mode 100644 x-pack/plugins/index_lifecycle_management/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/api/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/app.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/lib/find_errors.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/lib/manage_angular_lifecycle.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/main.html
create mode 100644 x-pack/plugins/index_lifecycle_management/public/register_management_section.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/register_routes.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/landing/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/landing/landing.container.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/landing/landing.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.container.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.container.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index_template.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.container.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.container.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.container.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.container.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.container.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.container.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.container.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.less
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/form_errors.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.container.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/actions/general.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/actions/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/actions/index_template.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/constants.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/reducers/general.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/reducers/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/reducers/index_template.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/reducers/nodes.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/selectors/general.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/selectors/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/selectors/index_template.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/selectors/nodes.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/store.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/call_with_request_factory/call_with_request_factory.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/call_with_request_factory/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/check_license/check_license.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/check_license/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_custom_error.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_unknown_error.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/is_es_error_factory.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/register_license_checker/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/lib/register_license_checker/register_license_checker.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/indices/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_bootstrap_route.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_get_affected_route.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_indices_routes.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_create_route.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_lifecycle_routes.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_nodes_routes.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/policies/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_policies_routes.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/templates/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_get_route.js
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_templates_routes.js
diff --git a/package.json b/package.json
index da31a96649502..231f032931205 100644
--- a/package.json
+++ b/package.json
@@ -166,7 +166,6 @@
"querystring-browser": "1.0.4",
"raw-loader": "0.5.1",
"react": "^16.2.0",
- "react-ace": "6.0.0",
"react-addons-shallow-compare": "15.6.2",
"react-anything-sortable": "^1.7.4",
"react-color": "^2.13.8",
diff --git a/x-pack/package.json b/x-pack/package.json
index b652849340d58..1558920956dcf 100644
--- a/x-pack/package.json
+++ b/x-pack/package.json
@@ -130,6 +130,7 @@
"prop-types": "^15.6.0",
"puid": "1.0.5",
"react": "^16.2.0",
+ "react-ace": "6.0.0",
"react-clipboard.js": "^1.1.2",
"react-dom": "^16.2.0",
"react-markdown-renderer": "^1.4.0",
diff --git a/x-pack/plugins/index_lifecycle_management/TODO.md b/x-pack/plugins/index_lifecycle_management/TODO.md
new file mode 100644
index 0000000000000..3d39db9451560
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/TODO.md
@@ -0,0 +1,6 @@
+- PUT to override does not work, is there a PATCH or something?
+- Rename PRIMARY_NODES to PRIMARY_SHARDS per configuration.js label change
+- Policy type in the UI anywhere?
+- Diff editor to EUI
+- Index management changes to see status
+- CRUD UIs for managing policies and index templates
\ No newline at end of file
diff --git a/x-pack/plugins/index_lifecycle_management/common/constants/base_path.js b/x-pack/plugins/index_lifecycle_management/common/constants/base_path.js
new file mode 100644
index 0000000000000..5eea1d0ead4a4
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/common/constants/base_path.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export const BASE_PATH = '/management/elasticsearch/index_lifecycle_management/';
diff --git a/x-pack/plugins/index_lifecycle_management/common/constants/index.js b/x-pack/plugins/index_lifecycle_management/common/constants/index.js
new file mode 100644
index 0000000000000..59b61f7b99f98
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/common/constants/index.js
@@ -0,0 +1,8 @@
+/*
+ * 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 { PLUGIN } from './plugin';
+export { BASE_PATH } from './base_path';
diff --git a/x-pack/plugins/index_lifecycle_management/common/constants/plugin.js b/x-pack/plugins/index_lifecycle_management/common/constants/plugin.js
new file mode 100644
index 0000000000000..0261f57a93e8c
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/common/constants/plugin.js
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export const PLUGIN = {
+ ID: 'index_lifecycle_management'
+};
diff --git a/x-pack/plugins/index_lifecycle_management/index.js b/x-pack/plugins/index_lifecycle_management/index.js
new file mode 100644
index 0000000000000..2824f8e345d50
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/index.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+
+
+import { resolve } from 'path';
+import { registerTemplatesRoutes } from './server/routes/api/templates';
+import { registerNodesRoutes } from './server/routes/api/nodes';
+import { registerPoliciesRoutes } from './server/routes/api/policies';
+import { registerLifecycleRoutes } from './server/routes/api/lifecycle';
+import { registerIndicesRoutes } from './server/routes/api/indices';
+import { registerLicenseChecker } from './server/lib/register_license_checker';
+import { PLUGIN } from './common/constants';
+
+export function indexLifecycleManagement(kibana) {
+ return new kibana.Plugin({
+ id: PLUGIN.ID,
+ publicDir: resolve(__dirname, 'public'),
+ require: ['kibana', 'elasticsearch', 'xpack_main'],
+ uiExports: {
+ managementSections: [
+ 'plugins/index_lifecycle_management',
+ ]
+ },
+ init: function (server) {
+ registerLicenseChecker(server);
+ registerTemplatesRoutes(server);
+ registerNodesRoutes(server);
+ registerPoliciesRoutes(server);
+ registerLifecycleRoutes(server);
+ registerIndicesRoutes(server);
+ }
+ });
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/api/index.js b/x-pack/plugins/index_lifecycle_management/public/api/index.js
new file mode 100644
index 0000000000000..02018804fa462
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/api/index.js
@@ -0,0 +1,47 @@
+/*
+ * 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 chrome from 'ui/chrome';
+let httpClient;
+export const setHttpClient = (client) => {
+ httpClient = client;
+};
+const apiPrefix = chrome.addBasePath('/api/index_lifecycle_management');
+
+export async function loadNodes() {
+ const response = await httpClient.get(`${apiPrefix}/nodes/list`);
+ return response.data;
+}
+
+export async function loadIndexTemplates() {
+ const response = await httpClient.get(`${apiPrefix}/templates`);
+ return response.data;
+}
+
+export async function loadIndexTemplate(templateName) {
+ const response = await httpClient.get(`${apiPrefix}/template/${templateName}`);
+ return response.data;
+}
+
+export async function loadPolicies() {
+ const response = await httpClient.get(`${apiPrefix}/policies`);
+ return response.data;
+}
+
+export async function saveLifecycle(lifecycle, indexTemplatePatch) {
+ const response = await httpClient.post(`${apiPrefix}/lifecycle`, { lifecycle, indexTemplatePatch });
+ return response.data;
+}
+
+export async function bootstrap(indexName, aliasName) {
+ const response = await httpClient.post(`${apiPrefix}/indices/bootstrap`, { indexName, aliasName });
+ return response.data;
+}
+
+export async function getAffectedIndices(indexTemplateName, policyName) {
+ const response = await httpClient.get(`${apiPrefix}/indices/affected/${indexTemplateName}/${policyName}`);
+ return response.data;
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/app.js b/x-pack/plugins/index_lifecycle_management/public/app.js
new file mode 100644
index 0000000000000..2f5c19a16b684
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/app.js
@@ -0,0 +1,15 @@
+/*
+ * 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 { Landing } from './sections/landing';
+
+export const App = () => (
+
+);
diff --git a/x-pack/plugins/index_lifecycle_management/public/index.js b/x-pack/plugins/index_lifecycle_management/public/index.js
new file mode 100644
index 0000000000000..ccde49edbdf5d
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/index.js
@@ -0,0 +1,8 @@
+/*
+ * 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 './register_management_section';
+import './register_routes';
diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/find_errors.js b/x-pack/plugins/index_lifecycle_management/public/lib/find_errors.js
new file mode 100644
index 0000000000000..38d600622a8d4
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/lib/find_errors.js
@@ -0,0 +1,19 @@
+/*
+ * 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 hasErrors = (object, keysToIgnore = []) => {
+ const errors = [];
+ for (const [key, value] of Object.entries(object)) {
+ if (keysToIgnore.includes(key)) continue;
+ if (Array.isArray(value) && value.length > 0) {
+ return true;
+ errors.push(...value);
+ } else if (value) {
+ return hasErrors(value, keysToIgnore);
+ }
+ }
+ return false;
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/manage_angular_lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/lib/manage_angular_lifecycle.js
new file mode 100644
index 0000000000000..3813e632a0a73
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/lib/manage_angular_lifecycle.js
@@ -0,0 +1,23 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { unmountComponentAtNode } from 'react-dom';
+
+export const manageAngularLifecycle = ($scope, $route, elem) => {
+ const lastRoute = $route.current;
+
+ const deregister = $scope.$on('$locationChangeSuccess', () => {
+ const currentRoute = $route.current;
+ if (lastRoute.$$route.template === currentRoute.$$route.template) {
+ $route.current = lastRoute;
+ }
+ });
+
+ $scope.$on('$destroy', () => {
+ deregister && deregister();
+ elem && unmountComponentAtNode(elem);
+ });
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/main.html b/x-pack/plugins/index_lifecycle_management/public/main.html
new file mode 100644
index 0000000000000..1d1d0036e7fc1
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/main.html
@@ -0,0 +1,3 @@
+
+
+
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_management_section.js b/x-pack/plugins/index_lifecycle_management/public/register_management_section.js
new file mode 100644
index 0000000000000..16c4de6cf3236
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/register_management_section.js
@@ -0,0 +1,17 @@
+/*
+ * 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 { management } from 'ui/management';
+import { BASE_PATH } from '../common/constants';
+
+const esSection = management.getSection('elasticsearch');
+esSection.register('index_lifecycle_management', {
+ visible: true,
+ display: 'Index Lifecycle Management',
+ order: 1,
+ url: `#${BASE_PATH}home`
+});
+
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_routes.js b/x-pack/plugins/index_lifecycle_management/public/register_routes.js
new file mode 100644
index 0000000000000..c601c63299f31
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/register_routes.js
@@ -0,0 +1,44 @@
+/*
+ * 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 } from 'react-dom';
+import { Provider } from 'react-redux';
+import { setHttpClient } from './api';
+
+import { App } from './app';
+import { BASE_PATH } from '../common/constants/base_path';
+import { indexLifecycleManagementStore } from './store';
+
+import routes from 'ui/routes';
+
+import template from './main.html';
+import { manageAngularLifecycle } from './lib/manage_angular_lifecycle';
+
+const renderReact = async (elem) => {
+ render(
+
+
+ ,
+ elem
+ );
+};
+
+routes.when(`${BASE_PATH}:view?/:id?`, {
+ template: template,
+ controllerAs: 'indexManagement',
+ controller: class IndexManagementController {
+ constructor($scope, $route, $http) {
+ setHttpClient($http);
+
+ $scope.$$postDigest(() => {
+ const elem = document.getElementById('indexLifecycleManagementReactRoot');
+ renderReact(elem);
+ manageAngularLifecycle($scope, $route, elem);
+ });
+ }
+ }
+});
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/landing/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/landing/index.js
new file mode 100644
index 0000000000000..cc858ed0f20e5
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/landing/index.js
@@ -0,0 +1,10 @@
+/*
+ * 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 { Landing } from './landing.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/landing/landing.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/landing/landing.container.js
new file mode 100644
index 0000000000000..93e507b00ab7b
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/landing/landing.container.js
@@ -0,0 +1,24 @@
+/*
+ * 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 { connect } from 'react-redux';
+import { Landing as PresentationComponent } from './landing';
+import { fetchIndexTemplates } from '../../store/actions';
+import {
+ getIndexTemplates,
+} from '../../store/selectors';
+
+export const Landing = connect(
+ state => ({
+ indexTemplates: getIndexTemplates(state),
+ }),
+ {
+ fetchIndexTemplates
+ }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/landing/landing.js b/x-pack/plugins/index_lifecycle_management/public/sections/landing/landing.js
new file mode 100644
index 0000000000000..c9b2366e97e05
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/landing/landing.js
@@ -0,0 +1,43 @@
+/*
+ * 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, { PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import { Wizard } from '../wizard';
+
+export class Landing extends PureComponent {
+ static propTypes = {
+ fetchIndexTemplates: PropTypes.func.isRequired,
+
+ indexTemplates: PropTypes.array,
+ }
+
+ componentWillMount() {
+ this.props.fetchIndexTemplates();
+ }
+
+ render() {
+ const { indexTemplates } = this.props;
+
+ if (indexTemplates === null) {
+ // Loading...
+ return null;
+ }
+
+ if (indexTemplates.length === 0) {
+ return (
+ No index templates found.
+ );
+ }
+
+ return (
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.container.js
new file mode 100644
index 0000000000000..01ee20f34d5db
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.container.js
@@ -0,0 +1,41 @@
+/*
+ * 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 { connect } from 'react-redux';
+import { Configuration as PresentationComponent } from './configuration';
+import {
+ getNodeOptions,
+ getSelectedPrimaryShardCount,
+ getSelectedReplicaCount,
+ getSelectedNodeAttrs,
+ getIsPrimaryShardCountHigherThanSelectedNodeAttrsCount,
+} from '../../../../../../store/selectors';
+import {
+ setSelectedNodeAttrs,
+ setSelectedPrimaryShardCount,
+ setSelectedReplicaCount,
+ fetchNodes
+} from '../../../../../../store/actions';
+
+export const Configuration = connect(
+ state => ({
+ nodeOptions: getNodeOptions(state),
+ selectedNodeAttrs: getSelectedNodeAttrs(state),
+ selectedPrimaryShardCount: getSelectedPrimaryShardCount(state),
+ selectedReplicaCount: getSelectedReplicaCount(state),
+ selectedNodeAttrs: getSelectedNodeAttrs(state),
+ isPrimaryShardCountHigherThanSelectedNodeAttrsCount: getIsPrimaryShardCountHigherThanSelectedNodeAttrsCount(state),
+ }),
+ {
+ setSelectedNodeAttrs,
+ setSelectedPrimaryShardCount,
+ setSelectedReplicaCount,
+ fetchNodes
+ }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.js
new file mode 100644
index 0000000000000..a88ef8e7a97ee
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.js
@@ -0,0 +1,156 @@
+/*
+ * 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, { PureComponent } from 'react';
+import PropTypes from 'prop-types';
+
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiTitle,
+ EuiSpacer,
+ EuiSelect,
+ EuiFieldNumber,
+ EuiHorizontalRule,
+ EuiCallOut
+} from '@elastic/eui';
+import {
+ STRUCTURE_NODE_ATTRS,
+ STRUCTURE_PRIMARY_NODES,
+ STRUCTURE_REPLICAS
+} from '../../../../../../store/constants';
+
+import { ErrableFormRow } from '../../../../form_errors';
+
+export class Configuration extends PureComponent {
+ static propTypes = {
+ fetchNodes: PropTypes.func.isRequired,
+ setSelectedNodeAttrs: PropTypes.func.isRequired,
+ setSelectedPrimaryShardCount: PropTypes.func.isRequired,
+ setSelectedReplicaCount: PropTypes.func.isRequired,
+ validate: PropTypes.func.isRequired,
+
+ selectedPrimaryShardCount: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired,
+ selectedNodeAttrs: PropTypes.string.isRequired,
+ nodeOptions: PropTypes.array.isRequired,
+ selectedReplicaCount: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired,
+ isShowingErrors: PropTypes.bool.isRequired,
+ errors: PropTypes.object.isRequired,
+ isPrimaryShardCountHigherThanSelectedNodeAttrsCount: PropTypes.bool.isRequired,
+ };
+
+ componentWillMount() {
+ this.props.fetchNodes();
+ }
+
+ render() {
+ const {
+ setSelectedNodeAttrs,
+ setSelectedPrimaryShardCount,
+ setSelectedReplicaCount,
+ validate,
+
+ nodeOptions,
+ selectedPrimaryShardCount,
+ selectedReplicaCount,
+ selectedNodeAttrs,
+ errors,
+ isShowingErrors,
+ isPrimaryShardCountHigherThanSelectedNodeAttrsCount
+ } = this.props;
+
+ const primaryNodeErrors = isPrimaryShardCountHigherThanSelectedNodeAttrsCount ? (
+
+ The selected primary shard count is higher than the number of nodes matching the selected attributes.
+
+ ) : null;
+
+ return (
+
+
+
+ Configure options
+
+
+
+ {
+ await setSelectedNodeAttrs(e.target.value);
+ validate();
+ }}
+ options={nodeOptions}
+ />
+
+
+
+
+ Optimize these values for throughput. (Add more)
+
+
+
+
+
+
+ {
+ await setSelectedPrimaryShardCount(e.target.value);
+ validate();
+ }}
+ value={selectedPrimaryShardCount}
+ />
+
+
+
+
+ {
+ await setSelectedReplicaCount(e.target.value);
+ validate();
+ }}
+ value={selectedReplicaCount}
+ />
+
+
+
+
+ {primaryNodeErrors}
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/index.js
new file mode 100644
index 0000000000000..2a387bd853de8
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { Configuration } from './configuration.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/index.js
new file mode 100644
index 0000000000000..a7c5cfb8f3dab
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { TemplateSelection } from './template_selection.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.container.js
new file mode 100644
index 0000000000000..8a5f80515d899
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.container.js
@@ -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 { connect } from 'react-redux';
+import { TemplateSelection as PresentationComponent } from './template_selection';
+import {
+ getIndexTemplateOptions,
+ getSelectedIndexTemplateName,
+} from '../../../../../../store/selectors';
+import {
+ fetchIndexTemplates,
+ setSelectedIndexTemplate
+} from '../../../../../../store/actions';
+
+export const TemplateSelection = connect(
+ state => ({
+ templateOptions: getIndexTemplateOptions(state),
+ selectedIndexTemplateName: getSelectedIndexTemplateName(state),
+ }),
+ {
+ fetchIndexTemplates,
+ setSelectedIndexTemplate,
+ }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.js
new file mode 100644
index 0000000000000..5828749b4f70c
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.js
@@ -0,0 +1,85 @@
+/*
+ * 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, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+
+import { EuiSelect, EuiLink } from '@elastic/eui';
+import { ErrableFormRow } from '../../../../form_errors';
+import { STRUCTURE_TEMPLATE_NAME } from '../../../../../../store/constants';
+
+export class TemplateSelection extends PureComponent {
+ static propTypes = {
+ fetchIndexTemplates: PropTypes.func.isRequired,
+ setSelectedIndexTemplate: PropTypes.func.isRequired,
+ validate: PropTypes.func.isRequired,
+
+ selectedIndexTemplateName: PropTypes.string.isRequired,
+ templateOptions: PropTypes.array.isRequired,
+ errors: PropTypes.object.isRequired,
+ isShowingErrors: PropTypes.bool.isRequired,
+ };
+
+ componentWillMount() {
+ this.props.fetchIndexTemplates();
+ }
+
+ render() {
+ const {
+ setSelectedIndexTemplate,
+ validate,
+
+ templateOptions,
+ selectedIndexTemplateName,
+ errors,
+ isShowingErrors,
+ } = this.props;
+
+ // const noMatchingIndicesWarning =
+ // affectedIndices.length > 0 ? (
+ //
+ //
+ // The selected index template `{selectedIndexTemplateName}` matches
+ // existing indices which will not be affected by these changes.
+ //
+ //
+ // ) : null;
+
+ return (
+
+ {/* {noMatchingIndicesWarning} */}
+
+ Learn how to{' '}
+
+ add a new index template
+ .
+
+ }
+ >
+ {
+ await setSelectedIndexTemplate(e.target.value);
+ validate();
+ }}
+ options={templateOptions}
+ />
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index.js
new file mode 100644
index 0000000000000..20271f5f66ec2
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index.js
@@ -0,0 +1,10 @@
+/*
+ * 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 { IndexTemplate } from './index_template';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index_template.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index_template.js
new file mode 100644
index 0000000000000..ee693720a53be
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index_template.js
@@ -0,0 +1,85 @@
+/*
+ * 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, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+import { TemplateSelection } from './components/template_selection';
+import { Configuration } from './components/configuration';
+
+import {
+ EuiSpacer,
+ EuiTitle,
+ EuiHorizontalRule,
+ EuiButton
+} from '@elastic/eui';
+import { hasErrors } from '../../../../lib/find_errors';
+import { STRUCTURE_TEMPLATE_SELECTION, STRUCTURE_CONFIGURATION } from '../../../../store/constants';
+
+export class IndexTemplate extends Component {
+ static propTypes = {
+ done: PropTypes.func.isRequired,
+
+ errors: PropTypes.object,
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ isShowingErrors: false
+ };
+ }
+
+ validate = async () => {
+ await this.props.validate();
+ const noErrors = !hasErrors(this.props.errors);
+ return noErrors;
+ }
+
+ submit = async () => {
+ this.setState({ isShowingErrors: true });
+ if (await this.validate()) {
+ this.props.done();
+ }
+ }
+
+ render() {
+ const { errors } = this.props;
+ const { isShowingErrors } = this.state;
+
+ return (
+
+
+ Select a template
+
+
+
+
+
+
+
+ Next
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.container.js
new file mode 100644
index 0000000000000..bfeb21f8d32f1
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.container.js
@@ -0,0 +1,34 @@
+/*
+ * 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 { connect } from 'react-redux';
+import { ColdPhase as PresentationComponent } from './cold_phase';
+import {
+ getNodeOptions,
+ getPhase,
+ getPhaseData
+} from '../../../../../../store/selectors';
+import { setPhaseData, fetchNodes } from '../../../../../../store/actions';
+import {
+ PHASE_COLD,
+ PHASE_WARM,
+ PHASE_REPLICA_COUNT
+} from '../../../../../../store/constants';
+
+export const ColdPhase = connect(
+ state => ({
+ phaseData: getPhase(state, PHASE_COLD),
+ nodeOptions: getNodeOptions(state),
+ warmPhaseReplicaCount: getPhaseData(state, PHASE_WARM, PHASE_REPLICA_COUNT)
+ }),
+ {
+ setPhaseData: (key, value) => setPhaseData(PHASE_COLD, key, value),
+ fetchNodes
+ }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.js
new file mode 100644
index 0000000000000..7436558c68f46
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.js
@@ -0,0 +1,223 @@
+/*
+ * 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, { PureComponent } from 'react';
+import PropTypes from 'prop-types';
+
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiIcon,
+ EuiTitle,
+ EuiSpacer,
+ EuiText,
+ EuiTextColor,
+ EuiAccordion,
+ EuiFormRow,
+ EuiFieldNumber,
+ EuiSelect,
+ EuiSwitch,
+ EuiButtonEmpty,
+} from '@elastic/eui';
+import {
+ PHASE_ENABLED,
+ PHASE_ROLLOVER_ENABLED,
+ PHASE_ROLLOVER_ALIAS,
+ PHASE_ROLLOVER_AFTER,
+ PHASE_ROLLOVER_AFTER_UNITS,
+ PHASE_NODE_ATTRS,
+ PHASE_REPLICA_COUNT
+} from '../../../../../../store/constants';
+import { ErrableFormRow } from '../../../../form_errors';
+
+export class ColdPhase extends PureComponent {
+ static propTypes = {
+ setPhaseData: PropTypes.func.isRequired,
+ validate: PropTypes.func.isRequired,
+
+ isShowingErrors: PropTypes.bool.isRequired,
+ errors: PropTypes.object.isRequired,
+ phaseData: PropTypes.shape({
+ [PHASE_ENABLED]: PropTypes.bool.isRequired,
+ [PHASE_ROLLOVER_ENABLED]: PropTypes.bool.isRequired,
+ [PHASE_ROLLOVER_ALIAS]: PropTypes.string.isRequired,
+ [PHASE_ROLLOVER_AFTER]: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired,
+ [PHASE_ROLLOVER_AFTER_UNITS]: PropTypes.string.isRequired,
+ [PHASE_NODE_ATTRS]: PropTypes.string.isRequired,
+ [PHASE_REPLICA_COUNT]: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired
+ }).isRequired,
+ warmPhaseReplicaCount: PropTypes.number.isRequired,
+ nodeOptions: PropTypes.array.isRequired
+ };
+
+ componentWillMount() {
+ this.props.fetchNodes();
+ }
+
+ render() {
+ const {
+ setPhaseData,
+ validate,
+
+ phaseData,
+ nodeOptions,
+ warmPhaseReplicaCount,
+ errors,
+ isShowingErrors
+ } = this.props;
+
+ return (
+
+
+
+
+
+
+
+
+ Cold phase
+
+
+
+
+ This phase is optional. Re-allocate your indices again and
+ modify the number of replicas.
+
+
+
+ {isShowingErrors ? (
+
+
+ This phase contains errors that need to be fixed.
+
+
+ ) : null}
+
+
+ }
+ buttonClassName="ilmAccordion__button"
+ buttonContentClassName="ilmAccordion__buttonContent"
+ extraAction={
+ setPhaseData(PHASE_ENABLED, e.target.checked)}
+ label="Enable this phase"
+ />
+ }
+ >
+
+
+ Configuration
+
+
+
+
+
+ {
+ setPhaseData(PHASE_ROLLOVER_AFTER, e.target.value);
+ validate();
+ }}
+ />
+
+
+
+
+
+ setPhaseData(PHASE_ROLLOVER_AFTER_UNITS, e.target.value)
+ }
+ options={[
+ { value: 'd', text: 'days' },
+ { value: 'h', text: 'hours' }
+ ]}
+ />
+
+
+
+
+
+
+
+ {
+ await setPhaseData(PHASE_NODE_ATTRS, e.target.value);
+ validate();
+ }}
+ />
+
+
+
+
+
+ {
+ await setPhaseData(PHASE_REPLICA_COUNT, e.target.value);
+ validate();
+ }}
+ />
+
+
+
+
+
+ setPhaseData(PHASE_REPLICA_COUNT, warmPhaseReplicaCount)
+ }
+ >
+ Set to same as warm phase
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/index.js
new file mode 100644
index 0000000000000..e0d70ceb57726
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { ColdPhase } from './cold_phase.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.container.js
new file mode 100644
index 0000000000000..661489d2d9aa9
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.container.js
@@ -0,0 +1,20 @@
+/*
+ * 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 { connect } from 'react-redux';
+import { DeletePhase as PresentationComponent } from './delete_phase';
+import { getPhase } from '../../../../../../store/selectors';
+import { setPhaseData } from '../../../../../../store/actions';
+import { PHASE_DELETE } from '../../../../../../store/constants';
+
+export const DeletePhase = connect(
+ state => ({
+ phaseData: getPhase(state, PHASE_DELETE)
+ }),
+ {
+ setPhaseData: (key, value) => setPhaseData(PHASE_DELETE, key, value)
+ }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.js
new file mode 100644
index 0000000000000..9b1998df49500
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.js
@@ -0,0 +1,155 @@
+/*
+ * 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, { PureComponent } from 'react';
+import PropTypes from 'prop-types';
+
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiIcon,
+ EuiTitle,
+ EuiSpacer,
+ EuiText,
+ EuiTextColor,
+ EuiAccordion,
+ EuiFormRow,
+ EuiFieldNumber,
+ EuiSelect,
+ EuiSwitch,
+} from '@elastic/eui';
+import {
+ PHASE_ENABLED,
+ PHASE_ROLLOVER_ENABLED,
+ PHASE_ROLLOVER_AFTER,
+ PHASE_ROLLOVER_AFTER_UNITS,
+} from '../../../../../../store/constants';
+import { ErrableFormRow } from '../../../../form_errors';
+
+export class DeletePhase extends PureComponent {
+ static propTypes = {
+ setPhaseData: PropTypes.func.isRequired,
+ validate: PropTypes.func.isRequired,
+
+ isShowingErrors: PropTypes.bool.isRequired,
+ errors: PropTypes.object.isRequired,
+ phaseData: PropTypes.shape({
+ [PHASE_ENABLED]: PropTypes.bool.isRequired,
+ [PHASE_ROLLOVER_ENABLED]: PropTypes.bool.isRequired,
+ [PHASE_ROLLOVER_AFTER]: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired,
+ [PHASE_ROLLOVER_AFTER_UNITS]: PropTypes.string.isRequired
+ }).isRequired
+ };
+
+ render() {
+ const {
+ setPhaseData,
+ validate,
+ phaseData,
+ errors,
+ isShowingErrors
+ } = this.props;
+
+ return (
+
+
+
+
+
+
+
+
+ Delete phase
+
+
+
+
+ This phase is optional. Delete your indices after a
+ configured amount of time.
+
+
+
+ {isShowingErrors ? (
+
+
+ This phase contains errors that need to be fixed.
+
+
+ ) : null}
+
+
+ }
+ buttonClassName="ilmAccordion__button"
+ buttonContentClassName="ilmAccordion__buttonContent"
+ extraAction={
+ setPhaseData(PHASE_ENABLED, e.target.checked)}
+ label="Enable this phase"
+ />
+ }
+ >
+
+
+ Configuration
+
+
+
+
+
+ {
+ setPhaseData(PHASE_ROLLOVER_AFTER, e.target.value);
+ validate();
+ }}
+ />
+
+
+
+
+
+ setPhaseData(PHASE_ROLLOVER_AFTER_UNITS, e.target.value)
+ }
+ options={[
+ { value: 'd', text: 'days' },
+ { value: 'h', text: 'hours' }
+ ]}
+ />
+
+
+
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/index.js
new file mode 100644
index 0000000000000..5f909ab2c0f79
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { DeletePhase } from './delete_phase.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.container.js
new file mode 100644
index 0000000000000..1db810b49c19c
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.container.js
@@ -0,0 +1,23 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+
+
+import { connect } from 'react-redux';
+import { HotPhase as PresentationComponent } from './hot_phase';
+import { getPhase } from '../../../../../../store/selectors';
+import { setPhaseData } from '../../../../../../store/actions';
+import { PHASE_HOT } from '../../../../../../store/constants';
+
+export const HotPhase = connect(
+ state => ({
+ phaseData: getPhase(state, PHASE_HOT)
+ }),
+ {
+ setPhaseData: (key, value) => setPhaseData(PHASE_HOT, key, value)
+ },
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.js
new file mode 100644
index 0000000000000..4111e11a31c4d
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.js
@@ -0,0 +1,238 @@
+/*
+ * 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, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiIcon,
+ EuiTitle,
+ EuiSpacer,
+ EuiText,
+ EuiTextColor,
+ EuiAccordion,
+ EuiFieldNumber,
+ EuiSelect,
+ EuiSwitch
+} from '@elastic/eui';
+import {
+ PHASE_ROLLOVER_ALIAS,
+ PHASE_ROLLOVER_MAX_AGE,
+ PHASE_ROLLOVER_MAX_AGE_UNITS,
+ PHASE_ROLLOVER_MAX_SIZE_STORED,
+ PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS,
+ PHASE_ROLLOVER_ENABLED,
+ MAX_SIZE_TYPE_DOCUMENT
+} from '../../../../../../store/constants';
+
+import { ErrableFormRow } from '../../../../form_errors';
+
+export class HotPhase extends PureComponent {
+ static propTypes = {
+ setPhaseData: PropTypes.func.isRequired,
+ validate: PropTypes.func.isRequired,
+
+ isShowingErrors: PropTypes.bool.isRequired,
+ errors: PropTypes.object.isRequired,
+ phaseData: PropTypes.shape({
+ [PHASE_ROLLOVER_ALIAS]: PropTypes.string.isRequired,
+ [PHASE_ROLLOVER_MAX_AGE]: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired,
+ [PHASE_ROLLOVER_MAX_AGE_UNITS]: PropTypes.string.isRequired,
+ [PHASE_ROLLOVER_MAX_SIZE_STORED]: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired,
+ [PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS]: PropTypes.string.isRequired
+ }).isRequired
+ };
+
+ render() {
+ const {
+ validate,
+ setPhaseData,
+
+ phaseData,
+ isShowingErrors,
+ errors,
+ } = this.props;
+
+ return (
+
+
+
+
+
+
+
+
+ Hot phase
+
+
+
+ This phase is required. Rollover data by time and size.
+
+
+ {isShowingErrors ? (
+
+
+ This phase contains errors that need to be fixed.
+
+
+ ) : null}
+
+
+ }
+ buttonClassName="ilmAccordion__button"
+ buttonContentClassName="ilmAccordion__buttonContent"
+ >
+
+
+ Rollover configuration
+
+
+
{
+ await setPhaseData(PHASE_ROLLOVER_ENABLED, e.target.checked);
+ validate();
+ }}
+ label="Enable rollover"
+ />
+ {phaseData[PHASE_ROLLOVER_ENABLED] ? (
+
+
+ {/*
+
+
+ {
+ showErrorsFor(PHASE_ROLLOVER_ALIAS);
+ setPhaseData(PHASE_ROLLOVER_ALIAS, e.target.value);
+ }}
+ />
+
+
+ */}
+
+
+
+ {
+ await setPhaseData(
+ PHASE_ROLLOVER_MAX_SIZE_STORED,
+ e.target.value
+ );
+ validate();
+ }}
+ />
+
+
+
+
+ {
+ await setPhaseData(
+ PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS,
+ e.target.value
+ );
+ validate();
+ }}
+ options={[
+ { value: 'gb', text: 'gigabytes' },
+ { value: MAX_SIZE_TYPE_DOCUMENT, text: 'documents' }
+ ]}
+ />
+
+
+
+
+
+
+
+ {
+ await setPhaseData(PHASE_ROLLOVER_MAX_AGE, e.target.value);
+ validate();
+ }}
+ />
+
+
+
+
+ {
+ await setPhaseData(
+ PHASE_ROLLOVER_MAX_AGE_UNITS,
+ e.target.value
+ );
+ validate();
+ }}
+ options={[
+ { value: 'd', text: 'days' },
+ { value: 'h', text: 'hours' }
+ ]}
+ />
+
+
+
+
+ ) : null}
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/index.js
new file mode 100644
index 0000000000000..114e34c3ef4d0
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { HotPhase } from './hot_phase.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/index.js
new file mode 100644
index 0000000000000..7eb5def486c87
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { WarmPhase } from './warm_phase.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.container.js
new file mode 100644
index 0000000000000..b224e9b232769
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.container.js
@@ -0,0 +1,33 @@
+/*
+ * 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 { connect } from 'react-redux';
+import { WarmPhase as PresentationComponent } from './warm_phase';
+import {
+ getNodeOptions,
+ getPhase,
+ getSelectedReplicaCount,
+ getSelectedPrimaryShardCount
+} from '../../../../../../store/selectors';
+import { setPhaseData, fetchNodes } from '../../../../../../store/actions';
+import { PHASE_WARM, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../../../store/constants';
+
+export const WarmPhase = connect(
+ state => ({
+ phaseData: getPhase(state, PHASE_WARM),
+ hotPhaseReplicaCount: getSelectedReplicaCount(state),
+ hotPhasePrimaryShardCount: getSelectedPrimaryShardCount(state),
+ hotPhaseRolloverEnabled: getPhase(state, PHASE_HOT)[PHASE_ROLLOVER_ENABLED],
+ nodeOptions: getNodeOptions(state)
+ }),
+ {
+ setPhaseData: (key, value) => setPhaseData(PHASE_WARM, key, value),
+ fetchNodes
+ }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.js
new file mode 100644
index 0000000000000..dfd70d0876767
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.js
@@ -0,0 +1,358 @@
+/*
+ * 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, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiIcon,
+ EuiTitle,
+ EuiSpacer,
+ EuiText,
+ EuiTextColor,
+ EuiAccordion,
+ EuiFormRow,
+ EuiFieldNumber,
+ EuiSelect,
+ EuiSwitch,
+ EuiButtonEmpty,
+} from '@elastic/eui';
+import {
+ PHASE_ENABLED,
+ PHASE_ROLLOVER_ENABLED,
+ PHASE_ROLLOVER_ALIAS,
+ PHASE_FORCE_MERGE_ENABLED,
+ PHASE_FORCE_MERGE_SEGMENTS,
+ PHASE_NODE_ATTRS,
+ PHASE_PRIMARY_SHARD_COUNT,
+ PHASE_REPLICA_COUNT,
+ PHASE_ROLLOVER_AFTER,
+ PHASE_ROLLOVER_AFTER_UNITS
+} from '../../../../../../store/constants';
+import { ErrableFormRow } from '../../../../form_errors';
+
+export class WarmPhase extends Component {
+ static propTypes = {
+ setPhaseData: PropTypes.func.isRequired,
+ validate: PropTypes.func.isRequired,
+
+ isShowingErrors: PropTypes.bool.isRequired,
+ errors: PropTypes.object.isRequired,
+ phaseData: PropTypes.shape({
+ [PHASE_ENABLED]: PropTypes.bool.isRequired,
+ [PHASE_ROLLOVER_ENABLED]: PropTypes.bool.isRequired,
+ [PHASE_ROLLOVER_ALIAS]: PropTypes.string.isRequired,
+ [PHASE_FORCE_MERGE_ENABLED]: PropTypes.bool.isRequired,
+ [PHASE_FORCE_MERGE_SEGMENTS]: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired,
+ [PHASE_NODE_ATTRS]: PropTypes.string.isRequired,
+ [PHASE_PRIMARY_SHARD_COUNT]: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired,
+ [PHASE_REPLICA_COUNT]: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired,
+ [PHASE_ROLLOVER_AFTER]: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired,
+ [PHASE_ROLLOVER_AFTER_UNITS]: PropTypes.string.isRequired
+ }).isRequired,
+
+ hotPhaseReplicaCount: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired,
+ hotPhasePrimaryShardCount: PropTypes.oneOfType([
+ PropTypes.number,
+ PropTypes.string
+ ]).isRequired,
+
+ nodeOptions: PropTypes.array.isRequired
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ applyOnRollover: false
+ };
+ }
+
+ componentWillMount() {
+ this.props.fetchNodes();
+ }
+
+ render() {
+ const {
+ validate,
+ setPhaseData,
+
+ phaseData,
+ hotPhaseReplicaCount,
+ hotPhasePrimaryShardCount,
+ nodeOptions,
+ errors,
+ isShowingErrors,
+ hotPhaseRolloverEnabled
+ } = this.props;
+
+ return (
+
+
+
+
+
+
+
+
+ Warm phase
+
+
+
+
+ This phase is optional. Re-allocate indices, redefine number
+ of active shards, replicas, and compress even further.
+
+
+
+ {isShowingErrors ? (
+
+
+ This phase contains errors that need to be fixed.
+
+
+ ) : null}
+
+
+ }
+ buttonClassName="ilmAccordion__button"
+ buttonContentClassName="ilmAccordion__buttonContent"
+ extraAction={
+ {
+ await setPhaseData(PHASE_ENABLED, e.target.checked);
+ validate();
+ }}
+ label="Enable this phase"
+ />
+ }
+ >
+
+
+ Configuration
+
+
+ {hotPhaseRolloverEnabled ? (
+
+
+ {
+ await this.setState({ applyOnRollover: e.target.checked });
+ validate();
+ }}
+ />
+
+
+ ) : null}
+ {!this.state.applyOnRollover ? (
+
+
+
+ {
+ setPhaseData(PHASE_ROLLOVER_AFTER, e.target.value);
+ validate();
+ }}
+ />
+
+
+
+
+ {
+ await setPhaseData(
+ PHASE_ROLLOVER_AFTER_UNITS,
+ e.target.value
+ );
+ validate();
+ }}
+ options={[
+ { value: 'd', text: 'days' },
+ { value: 'h', text: 'hours' }
+ ]}
+ />
+
+
+
+ ) : null}
+
+
+
+
+ {
+ await setPhaseData(PHASE_NODE_ATTRS, e.target.value);
+ validate();
+ }}
+ />
+
+
+
+
+ {
+ await setPhaseData(PHASE_REPLICA_COUNT, e.target.value);
+ validate();
+ }}
+ />
+
+
+
+
+ {
+ await setPhaseData(
+ PHASE_REPLICA_COUNT,
+ hotPhaseReplicaCount
+ );
+ validate();
+ }}
+ >
+ Set to same as hot phase
+
+
+
+
+
+
+
+
+ Shrink
+
+
+
+
+
+
+
+ {
+ await setPhaseData(
+ PHASE_PRIMARY_SHARD_COUNT,
+ e.target.value
+ );
+ validate();
+ }}
+ />
+
+
+
+
+ {
+ await setPhaseData(
+ PHASE_PRIMARY_SHARD_COUNT,
+ hotPhasePrimaryShardCount
+ );
+ validate();
+ }}
+ >
+ Set to same as hot phase
+
+
+
+
+
+
+
+
+ Force merge
+
+
+
+
{
+ await setPhaseData(PHASE_FORCE_MERGE_ENABLED, e.target.checked);
+ validate();
+ }}
+ />
+
+
+
+
+ {
+ await setPhaseData(PHASE_FORCE_MERGE_SEGMENTS, e.target.value);
+ validate();
+ }}
+ />
+
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/index.js
new file mode 100644
index 0000000000000..d8a885b0b32f3
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { PolicyConfiguration } from './policy_configuration.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.container.js
new file mode 100644
index 0000000000000..a64806993fb5c
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.container.js
@@ -0,0 +1,48 @@
+/*
+ * 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 { connect } from 'react-redux';
+import { PolicyConfiguration as PresentationComponent } from './policy_configuration';
+import {
+ getSelectedPolicyName,
+ getAffectedIndexTemplates,
+ getSelectedIndexTemplateName,
+ getBootstrapEnabled,
+ getIndexName,
+ getAliasName,
+ getSaveAsNewPolicy,
+ getSelectedOriginalPolicyName
+} from '../../../../store/selectors';
+import {
+ setBootstrapEnabled,
+ setIndexName,
+ setAliasName,
+ setSelectedPolicyName,
+ setSaveAsNewPolicy
+} from '../../../../store/actions';
+
+export const PolicyConfiguration = connect(
+ state => ({
+ selectedPolicyName: getSelectedPolicyName(state),
+ selectedIndexTemplateName: getSelectedIndexTemplateName(state),
+ affectedIndexTemplates: getAffectedIndexTemplates(state),
+ bootstrapEnabled: getBootstrapEnabled(state),
+ indexName: getIndexName(state),
+ aliasName: getAliasName(state),
+ saveAsNewPolicy: getSaveAsNewPolicy(state),
+ originalPolicyName: getSelectedOriginalPolicyName(state)
+ }),
+ {
+ setBootstrapEnabled,
+ setIndexName,
+ setAliasName,
+ setSelectedPolicyName,
+ setSaveAsNewPolicy
+ }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.js
new file mode 100644
index 0000000000000..fbc308adb65c0
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.js
@@ -0,0 +1,254 @@
+/*
+ * 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, { Component, Fragment } from 'react';
+import PropTypes from 'prop-types';
+
+import {
+ EuiTitle,
+ EuiSpacer,
+ EuiCallOut,
+ EuiHorizontalRule,
+ EuiButton,
+ EuiFormRow,
+ EuiSwitch,
+ EuiFieldText,
+} from '@elastic/eui';
+import { HotPhase } from './components/hot_phase';
+import { WarmPhase } from './components/warm_phase';
+import { DeletePhase } from './components/delete_phase';
+import { ColdPhase } from './components/cold_phase';
+import {
+ PHASE_HOT,
+ PHASE_COLD,
+ PHASE_DELETE,
+ PHASE_WARM,
+ STRUCTURE_POLICY_NAME,
+ STRUCTURE_INDEX_NAME,
+ STRUCTURE_ALIAS_NAME,
+} from '../../../../store/constants';
+import { hasErrors } from '../../../../lib/find_errors';
+import { ErrableFormRow } from '../../form_errors';
+
+export class PolicyConfiguration extends Component {
+ static propTypes = {
+ setSelectedPolicyName: PropTypes.func.isRequired,
+ setSaveAsNewPolicy: PropTypes.func.isRequired,
+ setIndexName: PropTypes.func.isRequired,
+ setAliasName: PropTypes.func.isRequired,
+ setBootstrapEnabled: PropTypes.func.isRequired,
+ done: PropTypes.func.isRequired,
+ validate: PropTypes.func.isRequired,
+
+ affectedIndexTemplates: PropTypes.array.isRequired,
+ selectedIndexTemplateName: PropTypes.string.isRequired,
+ selectedPolicyName: PropTypes.string.isRequired,
+ saveAsNewPolicy: PropTypes.bool.isRequired,
+ errors: PropTypes.object.isRequired,
+ bootstrapEnabled: PropTypes.bool.isRequired,
+ indexName: PropTypes.string.isRequired,
+ aliasName: PropTypes.string.isRequired,
+ originalPolicyName: PropTypes.string,
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ isShowingErrors: false,
+ };
+ }
+
+ validate = async () => {
+ await this.props.validate();
+ const noErrors = !hasErrors(this.props.errors);
+ return noErrors;
+ };
+
+ submit = async () => {
+ this.setState({ isShowingErrors: true });
+ if (await this.validate()) {
+ this.props.done();
+ }
+ };
+
+ render() {
+ const {
+ setSelectedPolicyName,
+ setSaveAsNewPolicy,
+ setBootstrapEnabled,
+ setIndexName,
+ setAliasName,
+ validate,
+
+ affectedIndexTemplates,
+ selectedIndexTemplateName,
+ selectedPolicyName,
+ saveAsNewPolicy,
+ errors,
+ bootstrapEnabled,
+ indexName,
+ aliasName,
+ originalPolicyName,
+ } = this.props;
+
+ const { isShowingErrors } = this.state;
+
+ const singleTemplate = (
+
+ This policy is only attached to the selected template{' '}
+ {selectedIndexTemplateName}.
+
+ );
+
+ const multiTemplate = (
+
+ This policy is attached to{' '}
+ {affectedIndexTemplates.length - 1} other template(s){' '}
+ besides {selectedIndexTemplateName}.
+
+ );
+
+ const warningMessage =
+ affectedIndexTemplates.length === 1 &&
+ affectedIndexTemplates[0] === selectedIndexTemplateName
+ ? singleTemplate
+ : multiTemplate;
+
+ return (
+
+
+ Edit policy: {selectedPolicyName}
+
+
+
+ Only the hot phase is required.
+
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {originalPolicyName ? (
+
+ {
+ await setSaveAsNewPolicy(e.target.checked);
+ validate();
+ }}
+ label={
+
+ Save this as a new policy so it does not
+ effect other templates.
+
+ }
+ />
+
+ ) : null}
+ {saveAsNewPolicy ? (
+
+ {
+ await setSelectedPolicyName(e.target.value);
+ validate();
+ }}
+ />
+
+ ) : null}
+
+
+ setBootstrapEnabled(e.target.checked)}
+ label={Create an index and alias for this template}
+ />
+
+ {bootstrapEnabled ? (
+
+
+ {
+ await setIndexName(e.target.value);
+ validate();
+ }}
+ />
+
+
+ {
+ await setAliasName(e.target.value);
+ validate();
+ }}
+ />
+
+
+ ) : null}
+
+
+
+
+
+ Next
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/index.js
new file mode 100644
index 0000000000000..447bc384c368d
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { PolicySelection } from './policy_selection.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.container.js
new file mode 100644
index 0000000000000..abe56ef4db032
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.container.js
@@ -0,0 +1,29 @@
+/*
+ * 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 { connect } from 'react-redux';
+import { PolicySelection as PresentationComponent } from './policy_selection';
+import {
+ getPolicies, getExistingPolicyName,
+} from '../../../../store/selectors';
+import {
+ fetchPolicies,
+ setSelectedPolicy,
+} from '../../../../store/actions';
+
+export const PolicySelection = connect(
+ state => ({
+ policies: getPolicies(state),
+ existingPolicyName: getExistingPolicyName(state),
+ }),
+ {
+ fetchPolicies,
+ setSelectedPolicy,
+ }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.js
new file mode 100644
index 0000000000000..52fe3a6cb1806
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.js
@@ -0,0 +1,117 @@
+/*
+ * 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, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+import {
+ EuiFlexGrid,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiIcon,
+ EuiTitle,
+ EuiSpacer,
+ EuiPanel,
+ EuiText
+} from '@elastic/eui';
+
+export class PolicySelection extends Component {
+ static propTypes = {
+ fetchPolicies: PropTypes.func.isRequired,
+ setSelectedPolicy: PropTypes.func.isRequired,
+ done: PropTypes.func.isRequired,
+
+ existingPolicyName: PropTypes.string.isRequired,
+ policies: PropTypes.array.isRequired
+ };
+
+ componentWillMount() {
+ this.props.fetchPolicies();
+ }
+
+ selectPolicy(policy) {
+ this.props.setSelectedPolicy(policy);
+ this.props.done();
+ }
+
+ render() {
+ const { policies, existingPolicyName } = this.props;
+
+ return (
+
+
+
+
+ Select a policy to start from
+
+
+
+ You can edit existing policies and save them under a new name
+ later
+
+
+
+ {/*
+
+
+
+ Hot
+
+
+
+
+ Warm
+
+
+
+
+ Cold
+
+
+
+
+ Delete
+
+
+
+ */}
+
+
+
+
+ this.selectPolicy(null)}
+ >
+
+
+ New policy
+
+
+
+ {policies.map(item => (
+
+ this.selectPolicy(item)}
+ >
+
+
+ {item.name}
+ {existingPolicyName === item.name ? '*' : ''}
+
+
+
+
+ ))}
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/index.js
new file mode 100644
index 0000000000000..defebab0131ea
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { Review } from './review.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.container.js
new file mode 100644
index 0000000000000..a809576f77dd9
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.container.js
@@ -0,0 +1,45 @@
+/*
+ * 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 { connect } from 'react-redux';
+import { Review as PresentationComponent } from './review';
+import {
+ getSelectedIndexTemplateName,
+ getAffectedIndexTemplates,
+ getTemplateDiff,
+ getLifecycle,
+ getSelectedPolicyName,
+ getSaveAsNewPolicy,
+ getSelectedOriginalPolicyName,
+ getAliasName,
+ getBootstrapEnabled,
+} from '../../../../store/selectors';
+import {
+ setSelectedPolicyName,
+ setSaveAsNewPolicy,
+} from '../../../../store/actions';
+
+export const Review = connect(
+ state => ({
+ selectedIndexTemplateName: getSelectedIndexTemplateName(state),
+ affectedIndexTemplates: getAffectedIndexTemplates(state),
+ templateDiff: getTemplateDiff(state),
+ lifecycle: getLifecycle(state),
+ bootstrapEnabled: getBootstrapEnabled(state),
+ aliasName: getAliasName(state),
+ selectedIndexTemplateName: getSelectedIndexTemplateName(state),
+ selectedPolicyName: getSelectedPolicyName(state),
+ saveAsNewPolicy: getSaveAsNewPolicy(state),
+ originalPolicyName: getSelectedOriginalPolicyName(state),
+ }),
+ {
+ setSelectedPolicyName,
+ setSaveAsNewPolicy,
+ }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.js
new file mode 100644
index 0000000000000..d5fbb7991bdf3
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.js
@@ -0,0 +1,177 @@
+/*
+ * 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, { Component } from 'react';
+import PropTypes from 'prop-types';
+
+import DiffEditor from 'react-ace/lib/diff';
+import './review.less';
+
+import 'brace/theme/github';
+import 'brace/mode/json';
+import 'brace/snippets/json';
+import 'brace/ext/language_tools';
+
+import {
+ EuiTitle,
+ EuiSpacer,
+ EuiHorizontalRule,
+ EuiButton,
+ EuiFlexItem,
+ EuiFlexGrid,
+ EuiPanel,
+ EuiText,
+} from '@elastic/eui';
+import { getAffectedIndices } from '../../../../api';
+
+export class Review extends Component {
+ static propTypes = {
+ setSelectedPolicyName: PropTypes.func.isRequired,
+ setSaveAsNewPolicy: PropTypes.func.isRequired,
+ done: PropTypes.func.isRequired,
+
+ selectedIndexTemplateName: PropTypes.string.isRequired,
+ affectedIndexTemplates: PropTypes.array.isRequired,
+ templateDiff: PropTypes.object.isRequired,
+ lifecycle: PropTypes.object.isRequired,
+ selectedPolicyName: PropTypes.string.isRequired,
+ saveAsNewPolicy: PropTypes.bool.isRequired,
+ originalPolicyName: PropTypes.string,
+ bootstrapEnabled: PropTypes.bool.isRequired,
+ aliasName: PropTypes.string.isRequired
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ selectedTab: 1,
+ affectedIndices: []
+ };
+ }
+
+ async componentWillMount() {
+ const affectedIndices = await getAffectedIndices(
+ this.props.selectedIndexTemplateName,
+ this.props.selectedPolicyName
+ );
+ this.setState({ affectedIndices });
+ }
+
+ render() {
+ const {
+ done,
+
+ selectedIndexTemplateName,
+ affectedIndexTemplates,
+ templateDiff,
+ lifecycle,
+ bootstrapEnabled,
+ aliasName
+ } = this.props;
+
+ const { affectedIndices } = this.state;
+
+ return (
+
+
+ Changes that will occur
+
+
+
+
+
+
+ {affectedIndexTemplates.length}
+
+
+
+ Index templates affected by this change (to the selected policy):
+
+
+ {affectedIndexTemplates.map(template => (
+ - {template}
+ ))}
+
+
+
+
+
+
+
+ {affectedIndices.length}
+
+
+
+ Indices affected by this change (to the selected policy):
+
+
+ {affectedIndices.map(index => - {index}
)}
+
+
+
+
+ {bootstrapEnabled ? (
+
+
+
+ New alias
+
+
+ Point to these new aliases going forward:
+
+ -
+ READ: {aliasName}
+
+ -
+ WRITE: {aliasName}
+
+
+
+
+
+ ) : null}
+
+
+
+
+ We will be changing the index template named `{
+ selectedIndexTemplateName
+ }`
+
+
+
+
+
+
+
+
done(lifecycle)}
+ >
+ Looks good, make these changes
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.less b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.less
new file mode 100644
index 0000000000000..862b1bd58e8c8
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.less
@@ -0,0 +1,5 @@
+.codeMarker {
+ background: #FFF677;
+ position:absolute;
+ z-index:20
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/form_errors.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/form_errors.js
new file mode 100644
index 0000000000000..fc3c29c4beb0c
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/form_errors.js
@@ -0,0 +1,36 @@
+/*
+ * 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, { cloneElement, Children, Fragment } from 'react';
+import { EuiFormRow } from '@elastic/eui';
+
+export const ErrableFormRow = ({
+ errorKey,
+ isShowingErrors,
+ errors,
+ children,
+ ...rest
+}) => {
+ return (
+ 0
+ }
+ error={errors[errorKey]}
+ {...rest}
+ >
+
+ {Children.map(children, child => cloneElement(child, {
+ isInvalid: isShowingErrors && errors[errorKey].length > 0,
+ }))}
+
+
+ );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/index.js
new file mode 100644
index 0000000000000..3a6f61a7c0492
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { Wizard } from './wizard.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.container.js
new file mode 100644
index 0000000000000..57eb484bcc0fd
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.container.js
@@ -0,0 +1,32 @@
+/*
+ * 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 { connect } from 'react-redux';
+import { Wizard as PresentationComponent } from './wizard';
+import { saveLifecycle } from '../../store/actions';
+import {
+ getIndexTemplatePatch,
+ getBootstrapEnabled,
+ getIndexName,
+ getAliasName,
+ validateLifecycle,
+} from '../../store/selectors';
+
+export const Wizard = connect(
+ state => ({
+ indexTemplatePatch: getIndexTemplatePatch(state),
+ bootstrapEnabled: getBootstrapEnabled(state),
+ indexName: getIndexName(state),
+ aliasName: getAliasName(state),
+ validateLifecycle: () => validateLifecycle(state),
+ }),
+ {
+ saveLifecycle
+ }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js
new file mode 100644
index 0000000000000..d2639b268da2f
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js
@@ -0,0 +1,165 @@
+/*
+ * 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, { Component } from 'react';
+import PropTypes from 'prop-types';
+import { toastNotifications } from 'ui/notify';
+import { IndexTemplate } from './components/index_template';
+import { PolicySelection } from './components/policy_selection';
+import { PolicyConfiguration } from './components/policy_configuration';
+import { Review } from './components/review';
+import {
+ EuiPage,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiTitle,
+ EuiSpacer,
+ EuiStepsHorizontal
+} from '@elastic/eui';
+import { bootstrap } from '../../api';
+import {
+ STRUCTURE_INDEX_TEMPLATE,
+ STRUCTURE_POLICY_CONFIGURATION
+} from '../../store/constants';
+
+export class Wizard extends Component {
+ static propTypes = {
+ saveLifecycle: PropTypes.func.isRequired,
+ validateLifecycle: PropTypes.func.isRequired,
+
+ indexTemplatePatch: PropTypes.object.isRequired,
+ bootstrapEnabled: PropTypes.bool.isRequired,
+ indexName: PropTypes.string.isRequired,
+ aliasName: PropTypes.string.isRequired
+ };
+
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ selectedStep: 1,
+ errors: this.getErrors()
+ };
+ }
+
+ onSelectedStepChanged = selectedStep => {
+ this.setState({
+ selectedStep
+ });
+ };
+
+ getErrors = () => {
+ return this.props.validateLifecycle();
+ };
+
+ validate = () => {
+ const errors = this.getErrors();
+ this.setState({ errors });
+ };
+
+ addLifecycle = async lifecycle => {
+ await this.props.saveLifecycle(lifecycle, this.props.indexTemplatePatch);
+ await this.bootstrap();
+ // this.onSelectedStepChanged(5);
+ };
+
+ bootstrap = async () => {
+ const { indexName, aliasName, bootstrapEnabled } = this.props;
+ if (!bootstrapEnabled) {
+ return;
+ }
+
+ const response = await bootstrap(indexName, aliasName);
+ if (response && response.acknowledged) {
+ toastNotifications.addSuccess(
+ 'Successfully bootstrapped an index and alias'
+ );
+ // Bounce back to management
+ // this.onSelectedStepChanged(1);
+ // TODO: also clear state?
+ } else {
+ toastNotifications.addDanger('Unable to bootstrap an index and alias');
+ }
+ };
+
+ renderContent() {
+ const { selectedStep, errors } = this.state;
+
+ switch (selectedStep) {
+ case 1:
+ return (
+ this.onSelectedStepChanged(2)}
+ />
+ );
+ case 2:
+ return this.onSelectedStepChanged(3)} />;
+ case 3:
+ return (
+ this.onSelectedStepChanged(4)}
+ />
+ );
+ case 4:
+ return ;
+ }
+ }
+
+ render() {
+ const steps = [
+ {
+ title: 'Select a template',
+ isSelected: this.state.selectedStep === 1,
+ isComplete: this.state.selectedStep > 1,
+ onClick: () => this.onSelectedStepChanged(1)
+ },
+ {
+ title: 'Select or create policy',
+ isSelected: this.state.selectedStep === 2,
+ isComplete: this.state.selectedStep > 2,
+ disabled: this.state.selectedStep < 2,
+ onClick: () => this.onSelectedStepChanged(2)
+ },
+ {
+ title: 'Configure policy',
+ isSelected: this.state.selectedStep === 3,
+ isComplete: this.state.selectedStep > 3,
+ disabled: this.state.selectedStep < 3,
+ onClick: () => this.onSelectedStepChanged(3)
+ },
+ {
+ title: 'Review and save',
+ isSelected: this.state.selectedStep === 4,
+ isComplete: this.state.selectedStep > 4,
+ disabled: this.state.selectedStep < 4,
+ onClick: () => this.onSelectedStepChanged(4)
+ }
+ ];
+
+ return (
+
+
+
+
+ Index lifecycle management
+
+
+
+
+
+
+ {this.renderContent()}
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/general.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/general.js
new file mode 100644
index 0000000000000..584488d4c2b42
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/general.js
@@ -0,0 +1,14 @@
+/*
+ * 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 { createAction } from 'redux-actions';
+
+export const setBootstrapEnabled = createAction('SET_BOOTSTRAP_ENABLED');
+export const setIndexName = createAction('SET_INDEX_NAME');
+export const setAliasName = createAction('SET_ALIAS_NAME');
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/index.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/index.js
new file mode 100644
index 0000000000000..621cbf007d3b2
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/index.js
@@ -0,0 +1,14 @@
+/*
+ * 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 * from './index_template';
+export * from './nodes';
+export * from './policies';
+export * from './lifecycle';
+export * from './general';
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/index_template.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/index_template.js
new file mode 100644
index 0000000000000..50eec52976059
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/index_template.js
@@ -0,0 +1,103 @@
+/*
+ * 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 { createAction } from 'redux-actions';
+import { toastNotifications } from 'ui/notify';
+import { loadIndexTemplates, loadIndexTemplate } from '../../api';
+import { getAlias } from '../selectors';
+import {
+ setPhaseData,
+ setIndexName,
+ setAliasName,
+ setSelectedPrimaryShardCount,
+ setSelectedReplicaCount,
+ setSelectedNodeAttrs
+} from '.';
+import {
+ PHASE_HOT,
+ PHASE_ROLLOVER_ALIAS,
+ PHASE_WARM,
+ PHASE_COLD,
+ PHASE_DELETE
+} from '../constants';
+
+export const fetchingIndexTemplates = createAction('FETCHING_INDEX_TEMPLATES');
+export const fetchedIndexTemplates = createAction('FETCHED_INDEX_TEMPLATES');
+export const fetchIndexTemplates = () => async dispatch => {
+ dispatch(fetchingIndexTemplates());
+
+ let templates;
+ try {
+ templates = await loadIndexTemplates();
+ } catch (err) {
+ return toastNotifications.addDanger(err.data.message);
+ }
+
+ dispatch(fetchedIndexTemplates(templates));
+};
+
+export const fetchedIndexTemplate = createAction('FETCHED_INDEX_TEMPLATE');
+export const fetchIndexTemplate = templateName => async dispatch => {
+ let template;
+ try {
+ template = await loadIndexTemplate(templateName);
+ } catch (err) {
+ return toastNotifications.addDanger(err.data.message);
+ }
+
+ if (template.settings && template.settings.index) {
+ dispatch(
+ setSelectedPrimaryShardCount(template.settings.index.number_of_shards)
+ );
+ dispatch(
+ setSelectedReplicaCount(template.settings.index.number_of_replicas)
+ );
+ if (
+ template.settings.index.routing &&
+ template.settings.index.routing.allocation &&
+ template.settings.index.routing.allocation.include
+ ) {
+ dispatch(
+ setSelectedNodeAttrs(
+ template.settings.index.routing.allocation.include.sattr_name
+ )
+ );
+ }
+ }
+
+ let indexPattern = template.index_patterns[0];
+ if (indexPattern.endsWith('*')) {
+ indexPattern = indexPattern.slice(0, -1);
+ }
+ dispatch(setIndexName(`${indexPattern}-00001`));
+ dispatch(setAliasName(`${indexPattern}-alias`));
+ dispatch(fetchedIndexTemplate(template));
+};
+
+export const setSelectedIndexTemplateName = createAction(
+ 'SET_SELECTED_INDEX_TEMPLATE_NAME'
+);
+
+export const setSelectedIndexTemplate = name => async (dispatch, getState) => {
+ // Await all of these to ensure they happen before the next round of validation
+ const promises = [
+ dispatch(setSelectedIndexTemplateName(name)),
+ dispatch(fetchIndexTemplate(name))
+ ];
+ const alias = getAlias(getState());
+ if (alias) {
+ promises.push(...[
+ dispatch(setPhaseData(PHASE_HOT, PHASE_ROLLOVER_ALIAS, alias)),
+ dispatch(setPhaseData(PHASE_WARM, PHASE_ROLLOVER_ALIAS, alias)),
+ dispatch(setPhaseData(PHASE_COLD, PHASE_ROLLOVER_ALIAS, alias)),
+ dispatch(setPhaseData(PHASE_DELETE, PHASE_ROLLOVER_ALIAS, alias))
+ ]);
+ }
+ await Promise.all(promises);
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js
new file mode 100644
index 0000000000000..676894d079093
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js
@@ -0,0 +1,25 @@
+/*
+ * 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 { createAction } from 'redux-actions';
+import { toastNotifications } from 'ui/notify';
+import { saveLifecycle as saveLifecycleApi } from '../../api';
+
+
+export const savedLifecycle = createAction('SAVED_LIFECYCLE');
+export const saveLifecycle = (lifecycle, indexTemplatePatch) => async dispatch => {
+ let saved;
+ try {
+ saved = await saveLifecycleApi(lifecycle, indexTemplatePatch);
+ }
+ catch (err) {
+ return toastNotifications.addDanger(err.data.message);
+ }
+
+ toastNotifications.addSuccess(`Successfully created lifecycle policy '${lifecycle.name}'`);
+
+ dispatch(savedLifecycle(saved));
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js
new file mode 100644
index 0000000000000..11b0a77be8106
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js
@@ -0,0 +1,25 @@
+/*
+ * 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 { createAction } from 'redux-actions';
+import { toastNotifications } from 'ui/notify';
+import { loadNodes } from '../../api';
+
+export const setSelectedNodeAttrs = createAction('SET_SELECTED_NODE_ATTRS');
+export const setSelectedPrimaryShardCount = createAction('SET_SELECTED_PRIMARY_SHARED_COUNT');
+export const setSelectedReplicaCount = createAction('SET_SELECTED_REPLICA_COUNT');
+export const fetchedNodes = createAction('FETCHED_NODES');
+export const fetchNodes = () => async dispatch => {
+ let nodes;
+ try {
+ nodes = await loadNodes();
+ }
+ catch (err) {
+ return toastNotifications.addDanger(err.data.message);
+ }
+
+ dispatch(fetchedNodes(nodes));
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js
new file mode 100644
index 0000000000000..47046331a4eb4
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js
@@ -0,0 +1,31 @@
+/*
+ * 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 { createAction } from 'redux-actions';
+import { toastNotifications } from 'ui/notify';
+import { loadPolicies } from '../../api';
+
+export const fetchedPolicies = createAction('FETCHED_POLICIES');
+export const fetchPolicies = () => async dispatch => {
+ let policies;
+ try {
+ policies = await loadPolicies();
+ }
+ catch (err) {
+ return toastNotifications.addDanger(err.data.message);
+ }
+
+ dispatch(fetchedPolicies(policies));
+};
+
+export const setSelectedPolicy = createAction('SET_SELECTED_POLICY');
+export const setSelectedPolicyName = createAction('SET_SELECTED_POLICY_NAME');
+export const setSaveAsNewPolicy = createAction('SET_SAVE_AS_NEW_POLICY');
+
+export const setPhaseData = createAction('SET_PHASE_DATA', (phase, key, value) => ({ phase, key, value }));
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/constants.js b/x-pack/plugins/index_lifecycle_management/public/store/constants.js
new file mode 100644
index 0000000000000..7b6e7076d87c5
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/constants.js
@@ -0,0 +1,104 @@
+/*
+ * 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 PHASE_HOT = 'hot';
+export const PHASE_WARM = 'warm';
+export const PHASE_COLD = 'cold';
+export const PHASE_DELETE = 'delete';
+
+export const PHASE_ENABLED = 'phaseEnabled';
+
+export const MAX_SIZE_TYPE_DOCUMENT = 'd';
+
+export const PHASE_ROLLOVER_ENABLED = 'rolloverEnabled';
+export const PHASE_ROLLOVER_ALIAS = 'selectedAlias';
+export const PHASE_ROLLOVER_MAX_AGE = 'selectedMaxAge';
+export const PHASE_ROLLOVER_MAX_AGE_UNITS = 'selectedMaxAgeUnits';
+export const PHASE_ROLLOVER_MAX_SIZE_STORED = 'selectedMaxSizeStored';
+export const PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS = 'selectedMaxSizeStoredUnits';
+export const PHASE_ROLLOVER_MAX_DOC_SIZE = 'selectedMaxDocSize';
+export const PHASE_ROLLOVER_AFTER = 'selectedAfter';
+export const PHASE_ROLLOVER_AFTER_UNITS = 'selectedAfterUnits';
+
+export const PHASE_FORCE_MERGE_SEGMENTS = 'selectedForceMergeSegments';
+export const PHASE_FORCE_MERGE_ENABLED = 'forceMergeEnabled';
+
+export const PHASE_NODE_ATTRS = 'selectedNodeAttrs';
+export const PHASE_PRIMARY_SHARD_COUNT = 'selectedPrimaryShardCount';
+export const PHASE_REPLICA_COUNT = 'selectedReplicaCount';
+
+export const PHASE_ATTRIBUTES_THAT_ARE_NUMBERS = [
+ PHASE_ROLLOVER_MAX_AGE,
+ PHASE_ROLLOVER_MAX_SIZE_STORED,
+ PHASE_ROLLOVER_MAX_DOC_SIZE,
+ PHASE_ROLLOVER_AFTER,
+ PHASE_FORCE_MERGE_SEGMENTS,
+ PHASE_PRIMARY_SHARD_COUNT,
+ PHASE_REPLICA_COUNT,
+];
+
+export const STRUCTURE_INDEX_TEMPLATE = 'indexTemplate';
+export const STRUCTURE_TEMPLATE_SELECTION = 'templateSelection';
+export const STRUCTURE_TEMPLATE_NAME = 'templateName';
+export const STRUCTURE_CONFIGURATION = 'configuration';
+export const STRUCTURE_NODE_ATTRS = 'node_attrs';
+export const STRUCTURE_PRIMARY_NODES = 'primary_nodes';
+export const STRUCTURE_REPLICAS = 'replicas';
+
+export const STRUCTURE_POLICY_CONFIGURATION = 'policyConfiguration';
+export const STRUCTURE_POLICY_NAME = 'policyName';
+export const STRUCTURE_INDEX_NAME = 'indexName';
+export const STRUCTURE_ALIAS_NAME = 'aliasName';
+
+export const ERROR_STRUCTURE = {
+ [STRUCTURE_INDEX_TEMPLATE]: {
+ [STRUCTURE_TEMPLATE_SELECTION]: {
+ [STRUCTURE_TEMPLATE_NAME]: []
+ },
+ [STRUCTURE_CONFIGURATION]: {
+ [STRUCTURE_NODE_ATTRS]: [],
+ [STRUCTURE_PRIMARY_NODES]: [],
+ [STRUCTURE_REPLICAS]: []
+ }
+ },
+ [STRUCTURE_POLICY_CONFIGURATION]: {
+ [STRUCTURE_POLICY_NAME]: [],
+ [STRUCTURE_INDEX_NAME]: [],
+ [STRUCTURE_ALIAS_NAME]: [],
+ [PHASE_HOT]: {
+ [PHASE_ROLLOVER_ALIAS]: [],
+ [PHASE_ROLLOVER_MAX_AGE]: [],
+ [PHASE_ROLLOVER_MAX_AGE_UNITS]: [],
+ [PHASE_ROLLOVER_MAX_SIZE_STORED]: [],
+ [PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS]: [],
+ [PHASE_ROLLOVER_MAX_DOC_SIZE]: []
+ },
+ [PHASE_WARM]: {
+ [PHASE_ROLLOVER_ALIAS]: [],
+ [PHASE_ROLLOVER_AFTER]: [],
+ [PHASE_ROLLOVER_AFTER_UNITS]: [],
+ [PHASE_NODE_ATTRS]: [],
+ [PHASE_PRIMARY_SHARD_COUNT]: [],
+ [PHASE_REPLICA_COUNT]: [],
+ [PHASE_FORCE_MERGE_SEGMENTS]: [],
+ },
+ [PHASE_COLD]: {
+ [PHASE_ROLLOVER_ALIAS]: [],
+ [PHASE_ROLLOVER_AFTER]: [],
+ [PHASE_ROLLOVER_AFTER_UNITS]: [],
+ [PHASE_NODE_ATTRS]: [],
+ [PHASE_REPLICA_COUNT]: [],
+ },
+ [PHASE_DELETE]: {
+ [PHASE_ROLLOVER_ALIAS]: [],
+ [PHASE_ROLLOVER_AFTER]: [],
+ [PHASE_ROLLOVER_AFTER_UNITS]: [],
+ },
+ }
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/index.js b/x-pack/plugins/index_lifecycle_management/public/store/index.js
new file mode 100644
index 0000000000000..808eb489bf913
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { indexLifecycleManagementStore } from './store';
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/reducers/general.js b/x-pack/plugins/index_lifecycle_management/public/store/reducers/general.js
new file mode 100644
index 0000000000000..abb56f5cdae2f
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/reducers/general.js
@@ -0,0 +1,38 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+
+
+import { handleActions } from 'redux-actions';
+import { setIndexName, setAliasName, setBootstrapEnabled } from '../actions/general';
+
+const defaultState = {
+ bootstrapEnabled: false,
+ indexName: '',
+ aliasName: '',
+};
+
+export const general = handleActions({
+ [setIndexName](state, { payload: indexName }) {
+ return {
+ ...state,
+ indexName,
+ };
+ },
+ [setAliasName](state, { payload: aliasName }) {
+ return {
+ ...state,
+ aliasName,
+ };
+ },
+ [setBootstrapEnabled](state, { payload: bootstrapEnabled }) {
+ return {
+ ...state,
+ bootstrapEnabled,
+ };
+ }
+}, defaultState);
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/reducers/index.js b/x-pack/plugins/index_lifecycle_management/public/store/reducers/index.js
new file mode 100644
index 0000000000000..7225d9e0be9f5
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/reducers/index.js
@@ -0,0 +1,21 @@
+/*
+ * 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 { combineReducers } from 'redux';
+import { indexTemplate } from './index_template';
+import { nodes } from './nodes';
+import { policies } from './policies';
+import { general } from './general';
+
+export const indexLifecycleManagement = combineReducers({
+ indexTemplate,
+ nodes,
+ policies,
+ general,
+});
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/reducers/index_template.js b/x-pack/plugins/index_lifecycle_management/public/store/reducers/index_template.js
new file mode 100644
index 0000000000000..19bc7af01954c
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/reducers/index_template.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+
+
+import { handleActions } from 'redux-actions';
+import {
+ fetchingIndexTemplates,
+ fetchedIndexTemplates,
+ setSelectedIndexTemplateName,
+ fetchedIndexTemplate
+} from '../actions/index_template';
+
+const defaultState = {
+ isLoading: false,
+ fullSelectedIndexTemplate: null,
+ selectedIndexTemplateName: '',
+ indexTemplates: null,
+};
+
+export const indexTemplate = handleActions(
+ {
+ [fetchingIndexTemplates](state) {
+ return {
+ ...state,
+ isLoading: true
+ };
+ },
+ [fetchedIndexTemplates](state, { payload: indexTemplates }) {
+ return {
+ ...state,
+ isLoading: false,
+ indexTemplates
+ };
+ },
+ [fetchedIndexTemplate](state, { payload: fullSelectedIndexTemplate }) {
+ return {
+ ...state,
+ fullSelectedIndexTemplate,
+ };
+ },
+ [setSelectedIndexTemplateName](state, { payload: selectedIndexTemplateName }) {
+ return {
+ ...state,
+ selectedIndexTemplateName
+ };
+ }
+ },
+ defaultState
+);
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/reducers/nodes.js b/x-pack/plugins/index_lifecycle_management/public/store/reducers/nodes.js
new file mode 100644
index 0000000000000..88d5b9a0f6d53
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/reducers/nodes.js
@@ -0,0 +1,61 @@
+/*
+ * 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 { handleActions } from 'redux-actions';
+import {
+ fetchedNodes,
+ setSelectedNodeAttrs,
+ setSelectedPrimaryShardCount,
+ setSelectedReplicaCount
+} from '../actions/nodes';
+
+const defaultState = {
+ isLoading: false,
+ selectedNodeAttrs: '',
+ selectedPrimaryShardCount: 1,
+ selectedReplicaCount: 1,
+ nodes: []
+};
+
+export const nodes = handleActions(
+ {
+ [fetchedNodes](state, { payload: nodes }) {
+ return {
+ ...state,
+ isLoading: false,
+ nodes
+ };
+ },
+ [setSelectedNodeAttrs](state, { payload: selectedNodeAttrs }) {
+ return {
+ ...state,
+ selectedNodeAttrs
+ };
+ },
+ [setSelectedPrimaryShardCount](state, { payload }) {
+ let selectedPrimaryShardCount = parseInt(payload);
+ if (isNaN(selectedPrimaryShardCount)) {
+ selectedPrimaryShardCount = '';
+ }
+ return {
+ ...state,
+ selectedPrimaryShardCount
+ };
+ },
+ [setSelectedReplicaCount](state, { payload }) {
+ let selectedReplicaCount = parseInt(payload);
+ if (isNaN(selectedReplicaCount)) {
+ selectedReplicaCount = '';
+ }
+
+ return {
+ ...state,
+ selectedReplicaCount
+ };
+ }
+ },
+ defaultState
+);
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js
new file mode 100644
index 0000000000000..8b68c8a5d1ceb
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js
@@ -0,0 +1,173 @@
+/*
+ * 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 { handleActions } from 'redux-actions';
+import {
+ fetchedPolicies,
+ setSelectedPolicy,
+ setSelectedPolicyName,
+ setSaveAsNewPolicy,
+ setPhaseData
+} from '../actions';
+import { policyFromES } from '../selectors';
+import {
+ PHASE_HOT,
+ PHASE_WARM,
+ PHASE_COLD,
+ PHASE_DELETE,
+ PHASE_ATTRIBUTES_THAT_ARE_NUMBERS,
+ PHASE_ENABLED,
+ PHASE_ROLLOVER_ENABLED,
+ PHASE_FORCE_MERGE_SEGMENTS,
+ PHASE_FORCE_MERGE_ENABLED,
+ PHASE_ROLLOVER_AFTER,
+ PHASE_NODE_ATTRS,
+ PHASE_PRIMARY_SHARD_COUNT,
+ PHASE_REPLICA_COUNT,
+ PHASE_ROLLOVER_AFTER_UNITS,
+ PHASE_ROLLOVER_MAX_AGE,
+ PHASE_ROLLOVER_MAX_AGE_UNITS,
+ PHASE_ROLLOVER_MAX_SIZE_STORED,
+ PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS,
+ PHASE_ROLLOVER_ALIAS,
+ PHASE_ROLLOVER_MAX_DOC_SIZE
+} from '../constants';
+
+export const defaultWarmPhase = {
+ [PHASE_ENABLED]: false,
+ [PHASE_ROLLOVER_ENABLED]: false,
+ [PHASE_ROLLOVER_ALIAS]: '',
+ [PHASE_FORCE_MERGE_SEGMENTS]: '',
+ [PHASE_FORCE_MERGE_ENABLED]: false,
+ [PHASE_ROLLOVER_AFTER]: '',
+ [PHASE_ROLLOVER_AFTER_UNITS]: 's',
+ [PHASE_NODE_ATTRS]: '',
+ [PHASE_PRIMARY_SHARD_COUNT]: '',
+ [PHASE_REPLICA_COUNT]: ''
+};
+
+export const defaultHotPhase = {
+ [PHASE_ENABLED]: true,
+ [PHASE_ROLLOVER_ENABLED]: true,
+ [PHASE_ROLLOVER_ALIAS]: '',
+ [PHASE_ROLLOVER_MAX_AGE]: '',
+ [PHASE_ROLLOVER_MAX_AGE_UNITS]: 's',
+ [PHASE_ROLLOVER_MAX_SIZE_STORED]: '',
+ [PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS]: 'gb',
+ [PHASE_ROLLOVER_MAX_DOC_SIZE]: '',
+};
+
+export const defaultColdPhase = {
+ [PHASE_ENABLED]: false,
+ [PHASE_ROLLOVER_ENABLED]: false,
+ [PHASE_ROLLOVER_ALIAS]: '',
+ [PHASE_ROLLOVER_AFTER]: '',
+ [PHASE_ROLLOVER_AFTER_UNITS]: 's',
+ [PHASE_NODE_ATTRS]: '',
+ [PHASE_REPLICA_COUNT]: ''
+};
+
+export const defaultDeletePhase = {
+ [PHASE_ENABLED]: false,
+ [PHASE_ROLLOVER_ENABLED]: false,
+ [PHASE_ROLLOVER_ALIAS]: '',
+ [PHASE_ROLLOVER_AFTER]: '',
+ [PHASE_ROLLOVER_AFTER_UNITS]: 's'
+};
+
+const defaultPolicy = {
+ name: '',
+ saveAsNew: true,
+ phases: {
+ [PHASE_HOT]: defaultHotPhase,
+ [PHASE_WARM]: defaultWarmPhase,
+ [PHASE_COLD]: defaultColdPhase,
+ [PHASE_DELETE]: defaultDeletePhase
+ }
+};
+
+const defaultState = {
+ isLoading: false,
+ originalPolicyName: undefined,
+ selectedPolicy: defaultPolicy,
+ policies: []
+};
+
+export const policies = handleActions(
+ {
+ [fetchedPolicies](state, { payload: policies }) {
+ return {
+ ...state,
+ isLoading: false,
+ policies
+ };
+ },
+ [setSelectedPolicy](state, { payload: selectedPolicy }) {
+ if (selectedPolicy === null) {
+ return {
+ ...state,
+ selectedPolicy: defaultPolicy,
+ };
+ }
+
+ return {
+ ...state,
+ originalPolicyName: selectedPolicy.name,
+ selectedPolicy: {
+ ...defaultPolicy,
+ ...policyFromES(selectedPolicy)
+ }
+ };
+ },
+ [setSelectedPolicyName](state, { payload: name }) {
+ return {
+ ...state,
+ selectedPolicy: {
+ ...state.selectedPolicy,
+ name
+ }
+ };
+ },
+ [setSaveAsNewPolicy](state, { payload: saveAsNew }) {
+ return {
+ ...state,
+ selectedPolicy: {
+ ...state.selectedPolicy,
+ saveAsNew
+ }
+ };
+ },
+ [setPhaseData](state, { payload }) {
+ const { phase, key } = payload;
+
+ let value = payload.value;
+ if (PHASE_ATTRIBUTES_THAT_ARE_NUMBERS.includes(key)) {
+ value = parseInt(value);
+ if (isNaN(value)) {
+ value = '';
+ }
+ }
+
+ return {
+ ...state,
+ selectedPolicy: {
+ ...state.selectedPolicy,
+ phases: {
+ ...state.selectedPolicy.phases,
+ [phase]: {
+ ...state.selectedPolicy.phases[phase],
+ [key]: value
+ }
+ }
+ }
+ };
+ }
+ },
+ defaultState
+);
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/general.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/general.js
new file mode 100644
index 0000000000000..41459d1bbb2c8
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/general.js
@@ -0,0 +1,12 @@
+/*
+ * 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 getBootstrapEnabled = state => state.general.bootstrapEnabled;
+export const getIndexName = state => state.general.indexName;
+export const getAliasName = state => state.general.aliasName;
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/index.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/index.js
new file mode 100644
index 0000000000000..621cbf007d3b2
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/index.js
@@ -0,0 +1,14 @@
+/*
+ * 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 * from './index_template';
+export * from './nodes';
+export * from './policies';
+export * from './lifecycle';
+export * from './general';
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/index_template.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/index_template.js
new file mode 100644
index 0000000000000..620dcd53be644
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/index_template.js
@@ -0,0 +1,170 @@
+/*
+ * 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 { createSelector } from 'reselect';
+import { merge, cloneDeep } from 'lodash';
+import {
+ getSaveAsNewPolicy,
+ getSelectedPolicyName,
+ getSelectedPrimaryShardCount,
+ getNodesFromSelectedNodeAttrs,
+ getSelectedReplicaCount,
+ getSelectedNodeAttrs
+} from '.';
+
+export const getIndexTemplates = state => state.indexTemplate.indexTemplates;
+export const getIndexTemplateOptions = createSelector(
+ [state => getIndexTemplates(state)],
+ templates => {
+ if (!templates) {
+ return [];
+ }
+
+ const options = templates.map(template => ({
+ text: template.name,
+ value: template.name
+ }));
+
+ options.sort((a, b) => a.text.localeCompare(b.text));
+ options.unshift({
+ text: '',
+ value: undefined
+ });
+
+ return options;
+ }
+);
+export const getSelectedIndexTemplateName = state =>
+ state.indexTemplate.selectedIndexTemplateName;
+
+export const getSelectedIndexTemplate = createSelector(
+ [
+ state => getSelectedIndexTemplateName(state),
+ state => getIndexTemplates(state)
+ ],
+ (selectedIndexTemplateName, allTemplates) => {
+ return allTemplates.find(
+ template => template.name === selectedIndexTemplateName
+ );
+ }
+);
+
+export const getFullSelectedIndexTemplate = state => state.indexTemplate.fullSelectedIndexTemplate;
+
+export const getExistingPolicyName = state => {
+ const template = getFullSelectedIndexTemplate(state);
+ if (template && template.settings && template.settings.index && template.settings.index.lifecycle) {
+ return template.settings.index.lifecycle.name;
+ }
+ return '';
+};
+
+export const getAlias = state => {
+ const template = getSelectedIndexTemplate(state);
+ if (template && template.settings) {
+ return template.settings.indexlifecycle.rollover_alias;
+ }
+ return undefined;
+};
+
+// TODO: add createSelector
+export const getAffectedIndexTemplates = state => {
+ const selectedIndexTemplateName = getSelectedIndexTemplateName(state);
+ const indexTemplates = [selectedIndexTemplateName];
+
+ const selectedPolicyName = getSelectedPolicyName(state);
+ const allTemplates = getIndexTemplates(state);
+ indexTemplates.push(
+ ...allTemplates.reduce((accum, template) => {
+ if (template.index_lifecycle_name === selectedPolicyName && template.name !== selectedIndexTemplateName) {
+ accum.push(template.name);
+ }
+ return accum;
+ }, [])
+ );
+
+ return indexTemplates;
+};
+
+// TODO: add createSelector
+export const getAffectedIndexPatterns = state => {
+ const indexPatterns = [...getSelectedIndexTemplate(state).index_patterns];
+
+ if (!getSaveAsNewPolicy(state)) {
+ const allTemplates = getIndexTemplates(state);
+ const selectedPolicyName = getSelectedPolicyName(state);
+ indexPatterns.push(
+ ...allTemplates.reduce((accum, template) => {
+ if (template.index_lifecycle_name === selectedPolicyName) {
+ accum.push(...template.index_patterns);
+ }
+ return accum;
+ }, [])
+ );
+ }
+
+ return indexPatterns;
+};
+
+export const getTemplateDiff = state => {
+ const fullIndexTemplate = getFullSelectedIndexTemplate(state) || { settings: {} };
+ return {
+ originalFullIndexTemplate: fullIndexTemplate,
+ newFullIndexTemplate: merge(cloneDeep(fullIndexTemplate), {
+ settings: {
+ index: {
+ number_of_shards: '' + getSelectedPrimaryShardCount(state),
+ number_of_replicas: '' + getSelectedReplicaCount(state),
+ lifecycle: {
+ name: getSelectedPolicyName(state)
+ },
+ routing: {
+ allocation: {
+ include: {
+ sattr_name: getSelectedNodeAttrs(state),
+ }
+ }
+ }
+ }
+ }
+ }),
+ // modifications: {
+ // settings: {
+ // index: {
+ // number_of_shards: getSelectedPrimaryShardCount(state),
+ // number_of_replicas: getSelectedReplicaCount(state),
+ // lifecycle: {
+ // name: getSelectedPolicyName(state),
+ // }
+ // }
+ // }
+ // }
+ };
+};
+
+export const getIsPrimaryShardCountHigherThanSelectedNodeAttrsCount = state => {
+ const primaryShardCount = getSelectedPrimaryShardCount(state);
+ const selectedNodeAttrsCount = getNodesFromSelectedNodeAttrs(state);
+
+ if (selectedNodeAttrsCount === null) {
+ return false;
+ }
+
+ return primaryShardCount > selectedNodeAttrsCount;
+};
+
+export const getIndexTemplatePatch = state => {
+ return {
+ indexTemplate: getSelectedIndexTemplateName(state),
+ primaryShardCount: getSelectedPrimaryShardCount(state),
+ replicaCount: getSelectedReplicaCount(state),
+ lifecycleName: getSelectedPolicyName(state),
+ nodeAttrs: getSelectedNodeAttrs(state)
+ };
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
new file mode 100644
index 0000000000000..235ebb4dd2062
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
@@ -0,0 +1,200 @@
+/*
+ * 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 {
+ PHASE_HOT,
+ PHASE_WARM,
+ PHASE_COLD,
+ PHASE_DELETE,
+ PHASE_ENABLED,
+ PHASE_ROLLOVER_ENABLED,
+ PHASE_ROLLOVER_MAX_AGE,
+ PHASE_ROLLOVER_MAX_SIZE_STORED,
+ STRUCTURE_INDEX_TEMPLATE,
+ STRUCTURE_CONFIGURATION,
+ STRUCTURE_NODE_ATTRS,
+ STRUCTURE_PRIMARY_NODES,
+ STRUCTURE_REPLICAS,
+ STRUCTURE_TEMPLATE_SELECTION,
+ STRUCTURE_TEMPLATE_NAME,
+ STRUCTURE_POLICY_NAME,
+ STRUCTURE_POLICY_CONFIGURATION,
+ STRUCTURE_INDEX_NAME,
+ STRUCTURE_ALIAS_NAME,
+ ERROR_STRUCTURE,
+ PHASE_ATTRIBUTES_THAT_ARE_NUMBERS
+} from '../constants';
+import {
+ getPhase,
+ getPhases,
+ phaseToES,
+ getSelectedPolicyName,
+ getSelectedIndexTemplateName,
+ isNumber,
+ getSelectedNodeAttrs,
+ getSelectedPrimaryShardCount,
+ getSelectedReplicaCount,
+ getSaveAsNewPolicy,
+ getSelectedOriginalPolicyName,
+ getBootstrapEnabled,
+ getIndexName,
+ getAliasName,
+} from '.';
+
+export const validatePhase = (type, phase) => {
+ const errors = {};
+
+ if (!phase[PHASE_ENABLED]) {
+ return errors;
+ }
+
+ if (phase[PHASE_ROLLOVER_ENABLED]) {
+ if (
+ !isNumber(phase[PHASE_ROLLOVER_MAX_AGE]) &&
+ !isNumber(phase[PHASE_ROLLOVER_MAX_SIZE_STORED])
+ ) {
+ errors[PHASE_ROLLOVER_MAX_AGE] = [
+ 'A rollover requires a max age, max docs, or max size.'
+ ];
+ errors[PHASE_ROLLOVER_MAX_SIZE_STORED] = [
+ 'A rollover requires a max age, max docs, or max size.'
+ ];
+ }
+ }
+
+ for (const numberedAttribute of PHASE_ATTRIBUTES_THAT_ARE_NUMBERS) {
+ if (phase.hasOwnProperty(numberedAttribute) && !phase[numberedAttribute] === '') {
+ if (!isNumber(phase[numberedAttribute])) {
+ errors[numberedAttribute].push('A number is required.');
+ }
+ else if (phase[numberedAttribute] < 0) {
+ errors[numberedAttribute].push('Only positive numbers allowed.');
+ }
+ }
+ }
+
+ return errors;
+};
+
+export const validateLifecycle = state => {
+ // This method of deep copy does not always work but it should be fine here
+ const errors = JSON.parse(JSON.stringify(ERROR_STRUCTURE));
+
+ if (!getSelectedIndexTemplateName(state)) {
+ errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][
+ STRUCTURE_TEMPLATE_NAME
+ ].push('An index template is required.');
+ }
+
+ if (!getSelectedNodeAttrs(state)) {
+ errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][
+ STRUCTURE_NODE_ATTRS
+ ].push('A node must be selected.');
+ }
+
+ if (!isNumber(getSelectedPrimaryShardCount(state))) {
+ errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][
+ STRUCTURE_PRIMARY_NODES
+ ].push('A value is required.');
+ }
+ else if (getSelectedPrimaryShardCount(state) < 0) {
+ errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][
+ STRUCTURE_PRIMARY_NODES
+ ].push('Only positive numbers allowed.');
+ }
+
+ if (!isNumber(getSelectedReplicaCount(state))) {
+ errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][
+ STRUCTURE_REPLICAS
+ ].push('A value is required.');
+ }
+ else if (getSelectedReplicaCount(state) < 0) {
+ errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][
+ STRUCTURE_REPLICAS
+ ].push('Only positive numbers allowed.');
+ }
+
+ if (!getSelectedPolicyName(state)) {
+ errors[STRUCTURE_POLICY_CONFIGURATION][STRUCTURE_POLICY_NAME].push('A policy name is required.');
+ }
+
+ if (getSaveAsNewPolicy(state) && getSelectedOriginalPolicyName(state) === getSelectedPolicyName(state)) {
+ errors[STRUCTURE_POLICY_CONFIGURATION][STRUCTURE_POLICY_NAME].push('The policy name must be different.');
+ }
+
+ // if (getSaveAsNewPolicy(state)) {
+ // const policyNames = getAllPolicyNamesFromTemplates(state);
+ // if (policyNames.includes(getSelectedPolicyName(state))) {
+ // errors[STRUCTURE_POLICY_CONFIGURATION][STRUCTURE_POLICY_NAME].push('That policy name is already used.');
+ // }
+ // }
+
+ if (getBootstrapEnabled(state) && !getIndexName(state)) {
+ errors[STRUCTURE_POLICY_CONFIGURATION][STRUCTURE_INDEX_NAME].push('An index name is required.');
+ }
+
+ if (getBootstrapEnabled(state) && !getAliasName(state)) {
+ errors[STRUCTURE_POLICY_CONFIGURATION][STRUCTURE_ALIAS_NAME].push('An alias name is required.');
+ }
+
+ errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_HOT] = {
+ ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_HOT],
+ ...validatePhase(PHASE_HOT, getPhase(state, PHASE_HOT))
+ };
+ errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_WARM] = {
+ ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_WARM],
+ ...validatePhase(PHASE_WARM, getPhase(state, PHASE_WARM))
+ };
+ errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_COLD] = {
+ ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_COLD],
+ ...validatePhase(PHASE_COLD, getPhase(state, PHASE_COLD))
+ };
+ errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_DELETE] = {
+ ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_DELETE],
+ ...validatePhase(PHASE_DELETE, getPhase(state, PHASE_DELETE))
+ };
+
+ return errors;
+};
+
+export const getLifecycle = state => {
+ const phases = Object.entries(getPhases(state)).reduce(
+ (accum, [phaseName, phase]) => {
+ // Hot is ALWAYS enabled
+ if (phaseName === PHASE_HOT) {
+ phase[PHASE_ENABLED] = true;
+ }
+
+ if (phase[PHASE_ENABLED]) {
+ accum[phaseName] = phaseToES(state, phase);
+
+ // These seem to be constants
+ // TODO: verify this assumption
+ if (phaseName === PHASE_HOT) {
+ accum[phaseName].after = '0s';
+ }
+
+ if (phaseName === PHASE_DELETE) {
+ accum[phaseName].actions = {
+ ...accum[phaseName].actions,
+ delete: {}
+ };
+ }
+ }
+ return accum;
+ },
+ {}
+ );
+
+ return {
+ name: getSelectedPolicyName(state),
+ //type, TODO: figure this out (jsut store it and not let the user change it?)
+ phases
+ };
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/nodes.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/nodes.js
new file mode 100644
index 0000000000000..1ad1e11e57045
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/nodes.js
@@ -0,0 +1,46 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+
+
+import { createSelector } from 'reselect';
+
+export const getNodes = state => state.nodes.nodes;
+export const getNodeOptions = createSelector(
+ [
+ state => getNodes(state),
+ ],
+ nodes => {
+ if (!nodes) {
+ return [];
+ }
+
+ const options = Object.keys(nodes).map(attrs => ({
+ text: attrs,
+ value: attrs,
+ }));
+
+ options.sort((a, b) => a.value.localeCompare(b.value));
+ options.unshift({
+ text: '',
+ value: undefined,
+ });
+
+ return options;
+ }
+);
+
+export const getSelectedPrimaryShardCount = state => state.nodes.selectedPrimaryShardCount;
+export const getSelectedReplicaCount = state => state.nodes.selectedReplicaCount;
+export const getSelectedNodeAttrs = state => state.nodes.selectedNodeAttrs;
+export const getNodesFromSelectedNodeAttrs = state => {
+ const nodes = getNodes(state)[getSelectedNodeAttrs(state)];
+ if (nodes) {
+ return nodes.length;
+ }
+ return null;
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
new file mode 100644
index 0000000000000..f0818f043ca94
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
@@ -0,0 +1,232 @@
+/*
+ * 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 {
+ defaultHotPhase,
+ defaultWarmPhase,
+ defaultColdPhase,
+ defaultDeletePhase
+} from '../reducers/policies';
+import {
+ PHASE_HOT,
+ PHASE_WARM,
+ PHASE_COLD,
+ PHASE_DELETE,
+ PHASE_ROLLOVER_AFTER,
+ PHASE_ROLLOVER_AFTER_UNITS,
+ PHASE_ROLLOVER_ENABLED,
+ PHASE_ROLLOVER_MAX_AGE,
+ PHASE_ROLLOVER_MAX_AGE_UNITS,
+ PHASE_ROLLOVER_MAX_SIZE_STORED,
+ PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS,
+ PHASE_NODE_ATTRS,
+ PHASE_FORCE_MERGE_ENABLED,
+ PHASE_FORCE_MERGE_SEGMENTS,
+ PHASE_PRIMARY_SHARD_COUNT,
+ PHASE_REPLICA_COUNT,
+ PHASE_ENABLED,
+ PHASE_ROLLOVER_ALIAS,
+ PHASE_ATTRIBUTES_THAT_ARE_NUMBERS,
+ MAX_SIZE_TYPE_DOCUMENT
+} from '../constants';
+import { getIndexTemplates } from '.';
+
+export const getPolicies = state => state.policies.policies;
+export const getSelectedPolicy = state => state.policies.selectedPolicy;
+export const getSelectedOriginalPolicyName = state => state.policies.originalPolicyName;
+
+export const getSaveAsNewPolicy = state =>
+ state.policies.selectedPolicy.saveAsNew;
+
+export const getSelectedPolicyName = state => {
+ if (!getSaveAsNewPolicy(state)) {
+ return getSelectedOriginalPolicyName(state);
+ }
+ return state.policies.selectedPolicy.name;
+};
+
+export const getAllPolicyNamesFromTemplates = state => {
+ return getIndexTemplates(state).map(template => template.index_lifecycle_name).filter(name => name);
+};
+
+export const getPhases = state => state.policies.selectedPolicy.phases;
+export const getPhase = (state, phase) =>
+ getPhases(state)[phase];
+export const getPhaseData = (state, phase, key) => {
+ if (PHASE_ATTRIBUTES_THAT_ARE_NUMBERS.includes(key)) {
+ return parseInt(getPhase(state, phase)[key]);
+ }
+ return getPhase(state, phase)[key];
+};
+
+export const splitSizeAndUnits = field => {
+ let size;
+ let units;
+
+ const result = /(\d+)(\w+)/.exec(field);
+ if (result) {
+ size = parseInt(result[1]) || 0;
+ units = result[2];
+ }
+
+ return {
+ size,
+ units
+ };
+};
+
+export const isNumber = value => typeof value === 'number';
+
+export const phaseFromES = (phase, defaultPolicy) => {
+ const policy = { ...defaultPolicy };
+
+ if (!phase) {
+ return policy;
+ }
+
+ policy[PHASE_ENABLED] = true;
+
+ if (phase.after) {
+ const { size: after, units: afterUnits } = splitSizeAndUnits(
+ phase.after
+ );
+ policy[PHASE_ROLLOVER_AFTER] = after;
+ policy[PHASE_ROLLOVER_AFTER_UNITS] = afterUnits;
+ }
+
+ if (phase.actions) {
+ const actions = phase.actions;
+
+ if (actions.rollover) {
+ const rollover = actions.rollover;
+ policy[PHASE_ROLLOVER_ENABLED] = true;
+ if (rollover.max_age) {
+ const { size: maxAge, units: maxAgeUnits } = splitSizeAndUnits(
+ rollover.max_age
+ );
+ policy[PHASE_ROLLOVER_MAX_AGE] = maxAge;
+ policy[PHASE_ROLLOVER_MAX_AGE_UNITS] = maxAgeUnits;
+ }
+ if (rollover.max_size) {
+ const { size: maxSize, units: maxSizeUnits } = splitSizeAndUnits(
+ rollover.max_size
+ );
+ policy[PHASE_ROLLOVER_MAX_SIZE_STORED] = maxSize;
+ policy[PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS] = maxSizeUnits;
+ }
+ if (rollover.max_docs) {
+ policy[PHASE_ROLLOVER_MAX_SIZE_STORED] = rollover.max_docs;
+ policy[PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS] = MAX_SIZE_TYPE_DOCUMENT;
+ }
+ } else {
+ policy[PHASE_ROLLOVER_ENABLED] = false;
+ }
+
+ if (actions.allocate) {
+ const allocate = actions.allocate;
+ if (allocate.require) {
+ policy[PHASE_NODE_ATTRS] = allocate.require._name;
+ }
+ }
+
+ if (actions.forcemerge) {
+ const forcemerge = actions.forcemerge;
+ policy[PHASE_FORCE_MERGE_ENABLED] = true;
+ policy[PHASE_FORCE_MERGE_SEGMENTS] = forcemerge.max_num_segments;
+ }
+
+ if (actions.shrink) {
+ policy[PHASE_PRIMARY_SHARD_COUNT] = actions.shrink.number_of_shards;
+ }
+
+ if (actions.replicas) {
+ const replicas = actions.replicas;
+ policy[PHASE_REPLICA_COUNT] = replicas.number_of_replicas;
+ }
+ }
+
+ return policy;
+};
+
+export const policyFromES = ({ name, type, phases }) => {
+ return {
+ name,
+ type,
+ phases: {
+ [PHASE_HOT]: phaseFromES(phases[PHASE_HOT], defaultHotPhase),
+ [PHASE_WARM]: phaseFromES(phases[PHASE_WARM], defaultWarmPhase),
+ [PHASE_COLD]: phaseFromES(phases[PHASE_COLD], defaultColdPhase),
+ [PHASE_DELETE]: phaseFromES(phases[PHASE_DELETE], defaultDeletePhase)
+ }
+ };
+};
+
+export const phaseToES = (state, phase) => {
+ const esPhase = {};
+
+ if (!phase[PHASE_ENABLED]) {
+ return esPhase;
+ }
+
+ if (isNumber(phase[PHASE_ROLLOVER_AFTER])) {
+ esPhase.after = `${phase[PHASE_ROLLOVER_AFTER]}${phase[PHASE_ROLLOVER_AFTER_UNITS]}`;
+ }
+
+ esPhase.actions = {};
+
+ if (phase[PHASE_ROLLOVER_ENABLED]) {
+ esPhase.actions.rollover = {
+ alias: phase[PHASE_ROLLOVER_ALIAS],
+ };
+
+ if (isNumber(phase[PHASE_ROLLOVER_MAX_AGE])) {
+ esPhase.actions.rollover.max_age = `${phase[PHASE_ROLLOVER_MAX_AGE]}${
+ phase[PHASE_ROLLOVER_MAX_AGE_UNITS]
+ }`;
+ } else if (isNumber(phase[PHASE_ROLLOVER_MAX_SIZE_STORED])) {
+ if (phase[PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS] === MAX_SIZE_TYPE_DOCUMENT) {
+ esPhase.actions.rollover.max_docs = phase[PHASE_ROLLOVER_MAX_SIZE_STORED];
+ } else {
+ esPhase.actions.rollover.max_size = `${phase[PHASE_ROLLOVER_MAX_SIZE_STORED]}${
+ phase[PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS]
+ }`;
+ }
+ }
+ }
+
+ if (phase[PHASE_NODE_ATTRS]) {
+ esPhase.actions.allocate = {
+ include: {}, // TODO: this seems to be a constant, confirm?
+ exclude: {}, // TODO: this seems to be a constant, confirm?
+ require: {
+ _name: phase[PHASE_NODE_ATTRS]
+ }
+ };
+ }
+
+ if (phase[PHASE_FORCE_MERGE_ENABLED]) {
+ esPhase.actions.forcemerge = {
+ max_num_segments: phase[PHASE_FORCE_MERGE_SEGMENTS]
+ };
+ }
+
+ if (isNumber(phase[PHASE_PRIMARY_SHARD_COUNT])) {
+ esPhase.actions.shrink = {
+ number_of_shards: phase[PHASE_PRIMARY_SHARD_COUNT]
+ };
+ }
+
+ if (isNumber(phase[PHASE_REPLICA_COUNT])) {
+ esPhase.actions.replicas = {
+ number_of_replicas: phase[PHASE_REPLICA_COUNT]
+ };
+ }
+
+ return esPhase;
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/store.js b/x-pack/plugins/index_lifecycle_management/public/store/store.js
new file mode 100644
index 0000000000000..3566efa9fff10
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/store/store.js
@@ -0,0 +1,21 @@
+/*
+ * 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 { createStore, applyMiddleware, compose } from 'redux';
+import thunk from 'redux-thunk';
+
+import { indexLifecycleManagement } from './reducers/';
+
+export const indexLifecycleManagementStore = (initialState = {}) => {
+ const enhancers = [ applyMiddleware(thunk) ];
+
+ window.__REDUX_DEVTOOLS_EXTENSION__ && enhancers.push(window.__REDUX_DEVTOOLS_EXTENSION__());
+ return createStore(
+ indexLifecycleManagement,
+ initialState,
+ compose(...enhancers)
+ );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/call_with_request_factory/call_with_request_factory.js b/x-pack/plugins/index_lifecycle_management/server/lib/call_with_request_factory/call_with_request_factory.js
new file mode 100644
index 0000000000000..b9a77a1a0362b
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/call_with_request_factory/call_with_request_factory.js
@@ -0,0 +1,18 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { once } from 'lodash';
+
+const callWithRequest = once((server) => {
+ const cluster = server.plugins.elasticsearch.getCluster('data');
+ return cluster.callWithRequest;
+});
+
+export const callWithRequestFactory = (server, request) => {
+ return (...args) => {
+ return callWithRequest(server)(request, ...args);
+ };
+};
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/call_with_request_factory/index.js b/x-pack/plugins/index_lifecycle_management/server/lib/call_with_request_factory/index.js
new file mode 100644
index 0000000000000..787814d87dff9
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/call_with_request_factory/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { callWithRequestFactory } from './call_with_request_factory';
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js b/x-pack/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js
new file mode 100644
index 0000000000000..19a7b56759269
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/check_license/__tests__/check_license.js
@@ -0,0 +1,146 @@
+/*
+ * 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 'expect.js';
+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 trial, standard, gold, platinum', () => {
+ 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);
+ });
+ });
+ });
+ });
+});
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/check_license/check_license.js b/x-pack/plugins/index_lifecycle_management/server/lib/check_license/check_license.js
new file mode 100644
index 0000000000000..8a5a7d7029b71
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/check_license/check_license.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export function checkLicense(xpackLicenseInfo) {
+ const pluginName = 'Index Management';
+
+ // 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: `You cannot use ${pluginName} because license information is not available at this time.`
+ };
+ }
+
+ const VALID_LICENSE_MODES = [
+ 'trial',
+ 'basic',
+ 'standard',
+ 'gold',
+ 'platinum'
+ ];
+
+ 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: `Your ${licenseType} license does not support ${pluginName}. Please upgrade your license.`
+ };
+ }
+
+ // License is valid but not active
+ if (!isLicenseActive) {
+ return {
+ isAvailable: false,
+ showLinks: true,
+ enableLinks: false,
+ message: `You cannot use ${pluginName} because your ${licenseType} license has expired.`
+ };
+ }
+
+ // License is valid and active
+ return {
+ isAvailable: true,
+ showLinks: true,
+ enableLinks: true
+ };
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/check_license/index.js b/x-pack/plugins/index_lifecycle_management/server/lib/check_license/index.js
new file mode 100644
index 0000000000000..f2c070fd44b6e
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/check_license/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { checkLicense } from './check_license';
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js
new file mode 100644
index 0000000000000..443744ccb0cc8
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_custom_error.js
@@ -0,0 +1,21 @@
+/*
+ * 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 'expect.js';
+import { wrapCustomError } from '../wrap_custom_error';
+
+describe('wrap_custom_error', () => {
+ describe('#wrapCustomError', () => {
+ it('should return a Boom object', () => {
+ const originalError = new Error('I am an error');
+ const statusCode = 404;
+ const wrappedError = wrapCustomError(originalError, statusCode);
+
+ expect(wrappedError.isBoom).to.be(true);
+ expect(wrappedError.output.statusCode).to.equal(statusCode);
+ });
+ });
+});
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js
new file mode 100644
index 0000000000000..394c182140000
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_es_error.js
@@ -0,0 +1,39 @@
+/*
+ * 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 'expect.js';
+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!');
+ });
+ });
+});
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
new file mode 100644
index 0000000000000..6d6a336417bef
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/__tests__/wrap_unknown_error.js
@@ -0,0 +1,19 @@
+/*
+ * 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 'expect.js';
+import { wrapUnknownError } from '../wrap_unknown_error';
+
+describe('wrap_unknown_error', () => {
+ describe('#wrapUnknownError', () => {
+ it('should return a Boom object', () => {
+ const originalError = new Error('I am an error');
+ const wrappedError = wrapUnknownError(originalError);
+
+ expect(wrappedError.isBoom).to.be(true);
+ });
+ });
+});
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/index.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/index.js
new file mode 100644
index 0000000000000..f275f15637091
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/index.js
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { wrapCustomError } from './wrap_custom_error';
+export { wrapEsError } from './wrap_es_error';
+export { wrapUnknownError } from './wrap_unknown_error';
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_custom_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_custom_error.js
new file mode 100644
index 0000000000000..890a366ac65c1
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_custom_error.js
@@ -0,0 +1,18 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import Boom from 'boom';
+
+/**
+ * Wraps a custom error into a Boom error response and returns it
+ *
+ * @param err Object error
+ * @param statusCode Error status code
+ * @return Object Boom error response
+ */
+export function wrapCustomError(err, statusCode) {
+ return Boom.wrap(err, statusCode);
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.js
new file mode 100644
index 0000000000000..6ac4d50c7e0fe
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.js
@@ -0,0 +1,30 @@
+/*
+ * 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, statusCodeToMessageMap = {}) {
+
+ 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.wrap(err, err.statusCode);
+ }
+
+ // Otherwise, use the custom message to create a Boom error response and
+ // return it
+ const message = statusCodeToMessageMap[statusCode];
+ return Boom.create(statusCode, message);
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_unknown_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_unknown_error.js
new file mode 100644
index 0000000000000..b0cdced7adbef
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_unknown_error.js
@@ -0,0 +1,17 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import Boom from 'boom';
+
+/**
+ * Wraps an unknown error into a Boom error response and returns it
+ *
+ * @param err Object Unknown error
+ * @return Object Boom error response
+ */
+export function wrapUnknownError(err) {
+ return Boom.wrap(err);
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js b/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
new file mode 100644
index 0000000000000..d50ff9480d3e4
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/__tests__/is_es_error_factory.js
@@ -0,0 +1,48 @@
+/*
+ * 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 'expect.js';
+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/plugins/index_lifecycle_management/server/lib/is_es_error_factory/index.js b/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/index.js
new file mode 100644
index 0000000000000..441648a8701e0
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { isEsErrorFactory } from './is_es_error_factory';
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/is_es_error_factory.js b/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/is_es_error_factory.js
new file mode 100644
index 0000000000000..80daac5bd496d
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/is_es_error_factory/is_es_error_factory.js
@@ -0,0 +1,18 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { memoize } from 'lodash';
+
+const esErrorsFactory = memoize((server) => {
+ return server.plugins.elasticsearch.getCluster('admin').errors;
+});
+
+export function isEsErrorFactory(server) {
+ const esErrors = esErrorsFactory(server);
+ return function isEsError(err) {
+ return err instanceof esErrors._Abstract;
+ };
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
new file mode 100644
index 0000000000000..b72f8cc769731
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
@@ -0,0 +1,72 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import expect from 'expect.js';
+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', (done) => {
+ const licensePreRouting = licensePreRoutingFactory(mockServer);
+ const stubRequest = {};
+ licensePreRouting(stubRequest, (response) => {
+ expect(response).to.be.an(Error);
+ expect(response.isBoom).to.be(true);
+ expect(response.output.statusCode).to.be(403);
+ done();
+ });
+ });
+ });
+
+ describe('isAvailable is true', () => {
+ beforeEach(() => {
+ mockLicenseCheckResults = {
+ isAvailable: true
+ };
+ });
+
+ it ('replies with nothing', (done) => {
+ const licensePreRouting = licensePreRoutingFactory(mockServer);
+ const stubRequest = {};
+ licensePreRouting(stubRequest, (response) => {
+ expect(response).to.be(undefined);
+ done();
+ });
+ });
+ });
+ });
+});
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/index.js b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/index.js
new file mode 100644
index 0000000000000..0743e443955f4
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { licensePreRoutingFactory } from './license_pre_routing_factory';
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js
new file mode 100644
index 0000000000000..b3720ab265393
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js
@@ -0,0 +1,29 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { once } from 'lodash';
+import { wrapCustomError } from '../error_wrappers';
+import { PLUGIN } from '../../../common/constants';
+
+export const licensePreRoutingFactory = once((server) => {
+ const xpackMainPlugin = server.plugins.xpack_main;
+
+ // License checking and enable/disable logic
+ function licensePreRouting(request, reply) {
+ const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults();
+ if (!licenseCheckResults.isAvailable) {
+ const error = new Error(licenseCheckResults.message);
+ const statusCode = 403;
+ const wrappedError = wrapCustomError(error, statusCode);
+ reply(wrappedError);
+ } else {
+ reply();
+ }
+ }
+
+ return licensePreRouting;
+});
+
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/register_license_checker/index.js b/x-pack/plugins/index_lifecycle_management/server/lib/register_license_checker/index.js
new file mode 100644
index 0000000000000..7b0f97c38d129
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/register_license_checker/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { registerLicenseChecker } from './register_license_checker';
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/register_license_checker/register_license_checker.js b/x-pack/plugins/index_lifecycle_management/server/lib/register_license_checker/register_license_checker.js
new file mode 100644
index 0000000000000..b05946e60b330
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/register_license_checker/register_license_checker.js
@@ -0,0 +1,21 @@
+/*
+ * 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 { checkLicense } from '../check_license';
+import { PLUGIN } from '../../../common/constants';
+
+export function registerLicenseChecker(server) {
+ const xpackMainPlugin = server.plugins.xpack_main;
+ const watcherPlugin = server.plugins.watcher;
+
+ mirrorPluginStatus(xpackMainPlugin, watcherPlugin);
+ 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/plugins/index_lifecycle_management/server/routes/api/indices/index.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/index.js
new file mode 100644
index 0000000000000..915fb695bb468
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { registerIndicesRoutes } from './register_indices_routes';
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_bootstrap_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_bootstrap_route.js
new file mode 100644
index 0000000000000..ad7128903b99c
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_bootstrap_route.js
@@ -0,0 +1,49 @@
+/*
+ * 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 { isEsErrorFactory } from '../../../lib/is_es_error_factory';
+import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
+import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory';
+
+async function bootstrap(callWithRequest, payload) {
+ await callWithRequest('indices.create', {
+ index: payload.indexName,
+ aliases: {
+ [payload.aliasName]: {}
+ },
+ settings: {
+ 'index.lifecycle.rollover_alias': payload.aliasName,
+ }
+ });
+}
+
+export function registerBootstrapRoute(server) {
+ const isEsError = isEsErrorFactory(server);
+ const licensePreRouting = licensePreRoutingFactory(server);
+
+ server.route({
+ path: '/api/index_lifecycle_management/indices/bootstrap',
+ method: 'POST',
+ handler: async (request, reply) => {
+ const callWithRequest = callWithRequestFactory(server, request);
+
+ try {
+ const response = await bootstrap(callWithRequest, request.payload);
+ reply(response);
+ } catch (err) {
+ if (isEsError(err)) {
+ return reply(wrapEsError(err));
+ }
+
+ reply(wrapUnknownError(err));
+ }
+ },
+ config: {
+ pre: [licensePreRouting]
+ }
+ });
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_get_affected_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_get_affected_route.js
new file mode 100644
index 0000000000000..73541518350f7
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_get_affected_route.js
@@ -0,0 +1,93 @@
+/*
+ * 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 { isEsErrorFactory } from '../../../lib/is_es_error_factory';
+import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
+import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_factory';
+
+async function fetchTemplates(callWithRequest) {
+ const params = {
+ method: 'GET',
+ path: '/_template',
+ // we allow 404 incase the user shutdown security in-between the check and now
+ ignore: [404]
+ };
+
+ return await callWithRequest('transport.request', params);
+}
+
+async function getAffectedIndices(
+ callWithRequest,
+ indexTemplateName,
+ policyName
+) {
+ const templates = await fetchTemplates(callWithRequest);
+
+ if (!templates || templates.length === 0) {
+ return [];
+ }
+
+ const indexPatterns = Object.entries(templates).reduce((accum, [templateName, template]) => {
+ if (templateName === indexTemplateName) {
+ accum.push(...template.index_patterns);
+ } else if (
+ template.settings &&
+ template.settings.index &&
+ template.settings.index.lifecycle &&
+ template.settings.index.lifecycle.name === policyName
+ ) {
+ accum.push(...template.index_patterns);
+ }
+ return accum;
+ }, []);
+
+ if (!indexPatterns || indexPatterns.length === 0) {
+ return [];
+ }
+
+ const indices = await callWithRequest('indices.get', {
+ index: indexPatterns
+ });
+
+ if (!indices) {
+ return [];
+ }
+
+ return Object.keys(indices);
+}
+
+export function registerGetAffectedRoute(server) {
+ const isEsError = isEsErrorFactory(server);
+ const licensePreRouting = licensePreRoutingFactory(server);
+
+ server.route({
+ path:
+ '/api/index_lifecycle_management/indices/affected/{indexTemplateName}/{policyName}',
+ method: 'GET',
+ handler: async (request, reply) => {
+ const callWithRequest = callWithRequestFactory(server, request);
+
+ try {
+ const response = await getAffectedIndices(
+ callWithRequest,
+ request.params.indexTemplateName,
+ request.params.policyName
+ );
+ reply(response);
+ } catch (err) {
+ if (isEsError(err)) {
+ return reply(wrapEsError(err));
+ }
+
+ reply(wrapUnknownError(err));
+ }
+ },
+ config: {
+ pre: [licensePreRouting]
+ }
+ });
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_indices_routes.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_indices_routes.js
new file mode 100644
index 0000000000000..1f94eb13d125e
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_indices_routes.js
@@ -0,0 +1,13 @@
+/*
+ * 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 { registerBootstrapRoute } from './register_bootstrap_route';
+import { registerGetAffectedRoute } from './register_get_affected_route';
+
+export function registerIndicesRoutes(server) {
+ registerBootstrapRoute(server);
+ registerGetAffectedRoute(server);
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/index.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/index.js
new file mode 100644
index 0000000000000..17f52a723405d
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { registerLifecycleRoutes } from './register_lifecycle_routes';
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_create_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_create_route.js
new file mode 100644
index 0000000000000..84e2637ab5a4c
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_create_route.js
@@ -0,0 +1,95 @@
+/*
+ * 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 { isEsErrorFactory } from '../../../lib/is_es_error_factory';
+import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
+import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory';
+import { merge } from 'lodash';
+
+async function createLifecycle(callWithRequest, lifecycle) {
+ const body = {
+ policy: {
+ phases: lifecycle.phases,
+ }
+ };
+ const params = {
+ method: 'PUT',
+ path: `/_xpack/index_lifecycle/${lifecycle.name}`,
+ ignore: [ 404 ],
+ body,
+ };
+
+ return await callWithRequest('transport.request', params);
+}
+
+async function getIndexTemplate(callWithRequest, indexTemplate) {
+ const response = await callWithRequest('indices.getTemplate', { name: indexTemplate });
+ return response[indexTemplate];
+}
+
+async function updateIndexTemplate(callWithRequest, indexTemplatePatch) {
+ // Fetch existing template
+ const template = await getIndexTemplate(callWithRequest, indexTemplatePatch.indexTemplate);
+ merge(template, {
+ settings: {
+ index: {
+ number_of_shards: indexTemplatePatch.primaryShardCount,
+ number_of_replicas: indexTemplatePatch.replicaCount,
+ lifecycle: {
+ name: indexTemplatePatch.lifecycleName,
+ },
+ routing: {
+ allocation: {
+ include: {
+ sattr_name: indexTemplatePatch.nodeAttrs,
+ }
+ }
+ }
+ }
+ }
+ });
+
+ const params = {
+ method: 'PUT',
+ path: `/_template/${indexTemplatePatch.indexTemplate}`,
+ ignore: [ 404 ],
+ body: template,
+ };
+
+ return await callWithRequest('transport.request', params);
+}
+
+export function registerCreateRoute(server) {
+ const isEsError = isEsErrorFactory(server);
+ const licensePreRouting = licensePreRoutingFactory(server);
+
+ server.route({
+ path: '/api/index_lifecycle_management/lifecycle',
+ method: 'POST',
+ handler: async (request, reply) => {
+ const callWithRequest = callWithRequestFactory(server, request);
+
+ try {
+ const response = await createLifecycle(callWithRequest, request.payload.lifecycle);
+ const response2 = await updateIndexTemplate(callWithRequest, request.payload.indexTemplatePatch);
+ reply([response, response2]);
+ } catch (err) {
+ if (isEsError(err)) {
+ return reply(wrapEsError(err));
+ }
+
+ reply(wrapUnknownError(err));
+ }
+ },
+ config: {
+ pre: [ licensePreRouting ]
+ }
+ });
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_lifecycle_routes.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_lifecycle_routes.js
new file mode 100644
index 0000000000000..ba179d14b8112
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_lifecycle_routes.js
@@ -0,0 +1,11 @@
+/*
+ * 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 { registerCreateRoute } from './register_create_route';
+
+export function registerLifecycleRoutes(server) {
+ registerCreateRoute(server);
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/index.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/index.js
new file mode 100644
index 0000000000000..ef0ac271ae60e
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { registerNodesRoutes } from './register_nodes_routes';
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.js
new file mode 100644
index 0000000000000..9320030ba41ed
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.js
@@ -0,0 +1,61 @@
+/*
+ * 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 { isEsErrorFactory } from '../../../lib/is_es_error_factory';
+import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
+import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory';
+
+function formatStats(stats) {
+ return Object.entries(stats.nodes).reduce((accum, [nodeId, stats]) => {
+ const attributes = stats.attributes || {};
+ for (const [key, value] of Object.entries(attributes)) {
+ const attributeString = `${key}:${value}`;
+ accum[attributeString] = accum[attributeString] || [];
+ accum[attributeString].push(nodeId);
+ }
+ return accum;
+ }, {});
+}
+
+async function fetchNodeStats(callWithRequest) {
+ const params = {
+ format: 'json'
+ };
+
+ return await callWithRequest('nodes.stats', params);
+}
+
+export function registerListRoute(server) {
+ const isEsError = isEsErrorFactory(server);
+ const licensePreRouting = licensePreRoutingFactory(server);
+
+ server.route({
+ path: '/api/index_lifecycle_management/nodes/list',
+ method: 'GET',
+ handler: async (request, reply) => {
+ const callWithRequest = callWithRequestFactory(server, request);
+
+ try {
+ const stats = await fetchNodeStats(callWithRequest);
+ const response = formatStats(stats);
+ reply(response);
+ } catch (err) {
+ if (isEsError(err)) {
+ return reply(wrapEsError(err));
+ }
+
+ reply(wrapUnknownError(err));
+ }
+ },
+ config: {
+ pre: [ licensePreRouting ]
+ }
+ });
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_nodes_routes.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_nodes_routes.js
new file mode 100644
index 0000000000000..2ce0bdbe77c44
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_nodes_routes.js
@@ -0,0 +1,11 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { registerListRoute } from './register_list_route';
+
+export function registerNodesRoutes(server) {
+ registerListRoute(server);
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/index.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/index.js
new file mode 100644
index 0000000000000..7c6103a3389ab
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { registerPoliciesRoutes } from './register_policies_routes';
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.js
new file mode 100644
index 0000000000000..6ec6745e80b21
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.js
@@ -0,0 +1,60 @@
+/*
+ * 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 { isEsErrorFactory } from '../../../lib/is_es_error_factory';
+import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
+import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory';
+
+function formatHits(hits) {
+ return Object.keys(hits).reduce((accum, lifecycleName) => {
+ const hit = hits[lifecycleName];
+ accum.push({
+ ...hit,
+ name: lifecycleName,
+ });
+ return accum;
+ }, []);
+}
+
+async function fetchPolicies(callWithRequest) {
+ const params = {
+ method: 'GET',
+ path: '/_xpack/index_lifecycle',
+ // we allow 404 incase the user shutdown security in-between the check and now
+ ignore: [ 404 ]
+ };
+
+ return await callWithRequest('transport.request', params);
+}
+
+export function registerFetchRoute(server) {
+ const isEsError = isEsErrorFactory(server);
+ const licensePreRouting = licensePreRoutingFactory(server);
+
+ server.route({
+ path: '/api/index_lifecycle_management/policies',
+ method: 'GET',
+ handler: async (request, reply) => {
+ const callWithRequest = callWithRequestFactory(server, request);
+
+ try {
+ const hits = await fetchPolicies(callWithRequest);
+ const response = formatHits(hits);
+ reply(response);
+ } catch (err) {
+ if (isEsError(err)) {
+ return reply(wrapEsError(err));
+ }
+
+ reply(wrapUnknownError(err));
+ }
+ },
+ config: {
+ pre: [ licensePreRouting ]
+ }
+ });
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_policies_routes.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_policies_routes.js
new file mode 100644
index 0000000000000..676121eadccb1
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_policies_routes.js
@@ -0,0 +1,11 @@
+/*
+ * 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 { registerFetchRoute } from './register_fetch_route';
+
+export function registerPoliciesRoutes(server) {
+ registerFetchRoute(server);
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/index.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/index.js
new file mode 100644
index 0000000000000..dc9a0acaaf09b
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { registerTemplatesRoutes } from './register_templates_routes';
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.js
new file mode 100644
index 0000000000000..37d15cf60a477
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.js
@@ -0,0 +1,81 @@
+/*
+ * 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 { isEsErrorFactory } from '../../../lib/is_es_error_factory';
+import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
+import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory';
+
+async function formatTemplates(templates, callWithRequest) {
+ const formattedTemplates = [];
+ const templateNames = Object.keys(templates);
+ for (const templateName of templateNames) {
+ const { settings, index_patterns } = templates[templateName]; // eslint-disable-line camelcase
+ const formattedTemplate = {
+ index_lifecycle_name: settings.index && settings.index.lifecycle ? settings.index.lifecycle.name : undefined,
+ index_patterns,
+ name: templateName,
+ };
+
+ const { indices } = await fetchIndices(index_patterns, callWithRequest);
+ formattedTemplate.indices = indices ? Object.keys(indices) : [];
+ formattedTemplates.push(formattedTemplate);
+ }
+ return formattedTemplates;
+}
+
+async function fetchTemplates(callWithRequest) {
+ const params = {
+ method: 'GET',
+ path: '/_template',
+ // we allow 404 incase the user shutdown security in-between the check and now
+ ignore: [ 404 ]
+ };
+
+ return await callWithRequest('transport.request', params);
+}
+
+async function fetchIndices(indexPatterns, callWithRequest) {
+ const params = {
+ method: 'GET',
+ path: `/${indexPatterns}/_stats`,
+ // we allow 404 incase the user shutdown security in-between the check and now
+ ignore: [ 404 ]
+ };
+
+ return await callWithRequest('transport.request', params);
+}
+
+export function registerFetchRoute(server) {
+ const isEsError = isEsErrorFactory(server);
+ const licensePreRouting = licensePreRoutingFactory(server);
+
+ server.route({
+ path: '/api/index_lifecycle_management/templates',
+ method: 'GET',
+ handler: async (request, reply) => {
+ const callWithRequest = callWithRequestFactory(server, request);
+
+ try {
+ const hits = await fetchTemplates(callWithRequest);
+ const templates = formatTemplates(hits, callWithRequest);
+ reply(templates);
+ } catch (err) {
+ if (isEsError(err)) {
+ return reply(wrapEsError(err));
+ }
+
+ reply(wrapUnknownError(err));
+ }
+ },
+ config: {
+ pre: [ licensePreRouting ]
+ }
+ });
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_get_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_get_route.js
new file mode 100644
index 0000000000000..690960e953c8c
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_get_route.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+
+
+import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
+import { isEsErrorFactory } from '../../../lib/is_es_error_factory';
+import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
+import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory';
+
+async function fetchTemplate(callWithRequest, templateName) {
+ const params = {
+ method: 'GET',
+ path: `/_template/${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) {
+ const isEsError = isEsErrorFactory(server);
+ const licensePreRouting = licensePreRoutingFactory(server);
+
+ server.route({
+ path: '/api/index_lifecycle_management/template/{templateName}',
+ method: 'GET',
+ handler: async (request, reply) => {
+ const callWithRequest = callWithRequestFactory(server, request);
+ const templateName = request.params.templateName;
+
+ try {
+ const template = await fetchTemplate(callWithRequest, templateName);
+ reply(template[templateName]);
+ } catch (err) {
+ if (isEsError(err)) {
+ return reply(wrapEsError(err));
+ }
+
+ reply(wrapUnknownError(err));
+ }
+ },
+ config: {
+ pre: [ licensePreRouting ]
+ }
+ });
+}
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_templates_routes.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_templates_routes.js
new file mode 100644
index 0000000000000..9750c0157b965
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_templates_routes.js
@@ -0,0 +1,16 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+
+
+
+import { registerFetchRoute } from './register_fetch_route';
+import { registerGetRoute } from './register_get_route';
+
+export function registerTemplatesRoutes(server) {
+ registerFetchRoute(server);
+ registerGetRoute(server);
+}
diff --git a/x-pack/yarn.lock b/x-pack/yarn.lock
index b33007ceb65d6..43681e79f6615 100644
--- a/x-pack/yarn.lock
+++ b/x-pack/yarn.lock
@@ -2004,6 +2004,10 @@ dfa@^1.0.0:
dependencies:
babel-runtime "^6.11.6"
+diff-match-patch@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.0.tgz#1cc3c83a490d67f95d91e39f6ad1f2e086b63048"
+
diff@1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf"
@@ -6078,6 +6082,16 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
+react-ace@6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-6.0.0.tgz#c211c21825f27343a7392f102493dc3ae099886d"
+ dependencies:
+ brace "^0.11.0"
+ diff-match-patch "^1.0.0"
+ lodash.get "^4.4.2"
+ lodash.isequal "^4.1.1"
+ prop-types "^15.5.8"
+
react-ace@^5.5.0, react-ace@^5.9.0:
version "5.9.0"
resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-5.9.0.tgz#427a1cc4869b960a6f9748aa7eb169a9269fc336"
From 318964f8024542149ee849e3154baa44aea594ff Mon Sep 17 00:00:00 2001
From: Chris Roberson
Date: Fri, 27 Apr 2018 10:34:09 -0400
Subject: [PATCH 003/102] Updates
---
.../wizard/components/review/review.js | 77 +++++++++----------
.../public/store/selectors/index_template.js | 49 +++++-------
2 files changed, 59 insertions(+), 67 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.js
index d5fbb7991bdf3..aa74c7398b907 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.js
@@ -4,10 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
-
-
-
-import React, { Component } from 'react';
+import React, { Fragment, Component } from 'react';
import PropTypes from 'prop-types';
import DiffEditor from 'react-ace/lib/diff';
@@ -44,14 +41,14 @@ export class Review extends Component {
saveAsNewPolicy: PropTypes.bool.isRequired,
originalPolicyName: PropTypes.string,
bootstrapEnabled: PropTypes.bool.isRequired,
- aliasName: PropTypes.string.isRequired
+ aliasName: PropTypes.string.isRequired,
};
constructor(props) {
super(props);
this.state = {
selectedTab: 1,
- affectedIndices: []
+ affectedIndices: [],
};
}
@@ -72,7 +69,7 @@ export class Review extends Component {
templateDiff,
lifecycle,
bootstrapEnabled,
- aliasName
+ aliasName,
} = this.props;
const { affectedIndices } = this.state;
@@ -91,7 +88,8 @@ export class Review extends Component {
- Index templates affected by this change (to the selected policy):
+ Index templates affected by this change (to
+ the selected policy):
+ }
+ >
+ {
+ await setPhaseData(PHASE_ROLLOVER_ENABLED, e.target.checked);
+ }}
+ label="Enable rollover"
+ />
+
+ {phaseData[PHASE_ROLLOVER_ENABLED] ? (
+
+
+
+
+
+ {
+ await setPhaseData(
+ PHASE_ROLLOVER_MAX_SIZE_STORED,
+ e.target.value
+ );
+ }}
+ min={1}
+ />
+
+
+
+
+ {
+ await setPhaseData(
+ PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS,
+ e.target.value
+ );
+ }}
+ options={[
+ { value: 'gb', text: 'gigabytes' },
+ { value: MAX_SIZE_TYPE_DOCUMENT, text: 'documents' }
+ ]}
+ />
+
+
+
+
+
+
+
+ {
+ await setPhaseData(PHASE_ROLLOVER_MAX_AGE, e.target.value);
+ }}
+ min={1}
+ />
+
+
+
+
+ {
+ await setPhaseData(
+ PHASE_ROLLOVER_MAX_AGE_UNITS,
+ e.target.value
+ );
+ }}
+ options={[
+ { value: 'd', text: 'days' },
+ { value: 'h', text: 'hours' },
+ ]}
+ />
+
+
+
+
+ ) : null}
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/index.js
new file mode 100644
index 0000000000000..114e34c3ef4d0
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { HotPhase } from './hot_phase.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/index.js
new file mode 100644
index 0000000000000..885e965c46c4b
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { NodeAttrsDetails } from './node_attrs_details.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js
new file mode 100644
index 0000000000000..3128a38c2c34f
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/node_attrs_details.container.js
@@ -0,0 +1,18 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { connect } from 'react-redux';
+import { NodeAttrsDetails as PresentationComponent } from './node_attrs_details';
+import { getNodeDetails, getExistingAllocationRules } from '../../../../store/selectors';
+import { fetchNodeDetails } from '../../../../store/actions';
+
+export const NodeAttrsDetails = connect(
+ (state, ownProps) => ({
+ details: getNodeDetails(state, ownProps.selectedNodeAttrs),
+ allocationRules: getExistingAllocationRules(state),
+ }),
+ { fetchNodeDetails }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/node_attrs_details.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/node_attrs_details.js
new file mode 100644
index 0000000000000..7cb2977e706ab
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/node_attrs_details.js
@@ -0,0 +1,80 @@
+/*
+ * 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, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+
+import {
+ EuiFlyoutBody,
+ EuiFlyoutFooter,
+ EuiFlyout,
+ EuiTitle,
+ EuiInMemoryTable,
+ EuiSpacer,
+ EuiButtonEmpty,
+ EuiCallOut,
+ EuiPortal,
+} from '@elastic/eui';
+
+export class NodeAttrsDetails extends PureComponent {
+ static propTypes = {
+ fetchNodeDetails: PropTypes.func.isRequired,
+ close: PropTypes.func.isRequired,
+
+ details: PropTypes.array,
+ selectedNodeAttrs: PropTypes.string.isRequired,
+ allocationRules: PropTypes.object,
+ };
+
+ componentWillMount() {
+ this.props.fetchNodeDetails(this.props.selectedNodeAttrs);
+ }
+
+ render() {
+ const { selectedNodeAttrs, allocationRules, details, close } = this.props;
+
+ return (
+
+
+
+
+ Nodes that contain the attribute: `{selectedNodeAttrs}`
+
+
+ {allocationRules ? (
+
+
+ Be aware that this index template has existing allocation rules
+ which will affect the list of nodes these indices can be allocated to.
+
+
+
+ ) : null}
+
+
+
+
+ Close
+
+
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/index.js
new file mode 100644
index 0000000000000..7eb5def486c87
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { WarmPhase } from './warm_phase.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js
new file mode 100644
index 0000000000000..b6d1c579de58f
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js
@@ -0,0 +1,33 @@
+/*
+ * 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 { connect } from 'react-redux';
+import { WarmPhase as PresentationComponent } from './warm_phase';
+import {
+ getNodeOptions,
+ getPhase,
+ getSelectedReplicaCount,
+ getSelectedPrimaryShardCount
+} from '../../../../store/selectors';
+import { setPhaseData, fetchNodes } from '../../../../store/actions';
+import { PHASE_WARM, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../store/constants';
+
+export const WarmPhase = connect(
+ state => ({
+ phaseData: getPhase(state, PHASE_WARM),
+ hotPhaseReplicaCount: Number(getSelectedReplicaCount(state)),
+ hotPhasePrimaryShardCount: Number(getSelectedPrimaryShardCount(state)),
+ hotPhaseRolloverEnabled: getPhase(state, PHASE_HOT)[PHASE_ROLLOVER_ENABLED],
+ nodeOptions: getNodeOptions(state)
+ }),
+ {
+ setPhaseData: (key, value) => setPhaseData(PHASE_WARM, key, value),
+ fetchNodes
+ }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
new file mode 100644
index 0000000000000..4320e043489f0
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
@@ -0,0 +1,352 @@
+/*
+ * 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, { Fragment, PureComponent } from 'react';
+import PropTypes from 'prop-types';
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiTitle,
+ EuiSpacer,
+ EuiText,
+ EuiTextColor,
+ EuiFormRow,
+ EuiFieldNumber,
+ EuiSelect,
+ EuiSwitch,
+ EuiButtonEmpty,
+ EuiDescribedFormGroup,
+ EuiBadge,
+ EuiButton,
+} from '@elastic/eui';
+import {
+ PHASE_ENABLED,
+ WARM_PHASE_ON_ROLLOVER,
+ PHASE_ROLLOVER_ALIAS,
+ PHASE_FORCE_MERGE_ENABLED,
+ PHASE_FORCE_MERGE_SEGMENTS,
+ PHASE_NODE_ATTRS,
+ PHASE_PRIMARY_SHARD_COUNT,
+ PHASE_REPLICA_COUNT,
+ PHASE_ROLLOVER_MINIMUM_AGE,
+ PHASE_ROLLOVER_MINIMUM_AGE_UNITS,
+ PHASE_SHRINK_ENABLED,
+} from '../../../../store/constants';
+import { ErrableFormRow } from '../../form_errors';
+import { LearnMoreLink } from '../../../../components/learn_more_link';
+
+export class WarmPhase extends PureComponent {
+ static propTypes = {
+ setPhaseData: PropTypes.func.isRequired,
+ showNodeDetailsFlyout: PropTypes.func.isRequired,
+
+ isShowingErrors: PropTypes.bool.isRequired,
+ errors: PropTypes.object.isRequired,
+ phaseData: PropTypes.shape({
+ [PHASE_ENABLED]: PropTypes.bool.isRequired,
+ [WARM_PHASE_ON_ROLLOVER]: PropTypes.bool.isRequired,
+ [PHASE_ROLLOVER_ALIAS]: PropTypes.string.isRequired,
+ [PHASE_FORCE_MERGE_ENABLED]: PropTypes.bool.isRequired,
+ [PHASE_FORCE_MERGE_SEGMENTS]: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
+ .isRequired,
+ [PHASE_NODE_ATTRS]: PropTypes.string.isRequired,
+ [PHASE_PRIMARY_SHARD_COUNT]: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
+ .isRequired,
+ [PHASE_REPLICA_COUNT]: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
+ [PHASE_ROLLOVER_MINIMUM_AGE]: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
+ [PHASE_ROLLOVER_MINIMUM_AGE_UNITS]: PropTypes.string.isRequired,
+ }).isRequired,
+
+ hotPhaseReplicaCount: PropTypes.number.isRequired,
+ hotPhasePrimaryShardCount: PropTypes.number.isRequired,
+
+ nodeOptions: PropTypes.array.isRequired,
+ };
+
+ componentWillMount() {
+ this.props.fetchNodes();
+ }
+
+ render() {
+ const {
+ setPhaseData,
+ showNodeDetailsFlyout,
+
+ phaseData,
+ hotPhaseReplicaCount,
+ hotPhasePrimaryShardCount,
+ nodeOptions,
+ errors,
+ isShowingErrors,
+ hotPhaseRolloverEnabled,
+ } = this.props;
+
+ return (
+
+ Warm phase{' '}
+ {phaseData[PHASE_ENABLED] ? (
+ Active
+ ) : null}
+
+ }
+ titleSize="s"
+ description={
+
+
+ Your index becomes read-only when it enters the warm phase. You can optimize this
+ phase for search.
+
+ {isShowingErrors ? (
+
+
+ This phase contains errors
+
+
+ ) : null}
+
+ }
+ fullWidth
+ >
+
+ {phaseData[PHASE_ENABLED] ? (
+
+
+
+ {
+ await setPhaseData(PHASE_ENABLED, false);
+ }}
+ >
+ Deactivate warm phase
+
+
+
+ {hotPhaseRolloverEnabled ? (
+
+ {
+ await setPhaseData(WARM_PHASE_ON_ROLLOVER, e.target.checked);
+ }}
+ />
+
+ ) : null}
+ {!phaseData[WARM_PHASE_ON_ROLLOVER] ? (
+
+
+
+ {
+ setPhaseData(PHASE_ROLLOVER_MINIMUM_AGE, e.target.value);
+ }}
+ min={1}
+ />
+
+
+
+
+ {
+ await setPhaseData(PHASE_ROLLOVER_MINIMUM_AGE_UNITS, e.target.value);
+ }}
+ options={[
+ { value: 'd', text: 'days' },
+ { value: 'h', text: 'hours' },
+ ]}
+ />
+
+
+
+ ) : null}
+
+
+
+ showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])}
+ >
+ View node details
+
+ ) : null
+ }
+ >
+ {
+ await setPhaseData(PHASE_NODE_ATTRS, e.target.value);
+ }}
+ />
+
+
+
+
+
+ {
+ await setPhaseData(PHASE_REPLICA_COUNT, e.target.value);
+ }}
+ min={0}
+ />
+
+
+
+
+ {
+ await setPhaseData(PHASE_REPLICA_COUNT, hotPhaseReplicaCount);
+ }}
+ >
+ Set to same as hot phase
+
+
+
+
+
+
+
+
+
+ Shrink
+
+
+
+ Shrink the index into a new index with fewer primary shards.{' '}
+
+
+
+
+
+
+ {
+ await setPhaseData(PHASE_SHRINK_ENABLED, e.target.checked);
+ }}
+ label="Shrink index"
+ />
+ {phaseData[PHASE_SHRINK_ENABLED] ? (
+
+
+
+
+ {
+ await setPhaseData(PHASE_PRIMARY_SHARD_COUNT, e.target.value);
+ }}
+ min={1}
+ />
+
+
+
+
+ {
+ await setPhaseData(
+ PHASE_PRIMARY_SHARD_COUNT,
+ hotPhasePrimaryShardCount
+ );
+ }}
+ >
+ Set to same as hot phase
+
+
+
+
+
+
+ ) : null}
+
+
+
+ Force merge
+
+
+
+ Reduce the number of segments in your shard by merging smaller files and clearing
+ deleted ones.
+
+
+
+
+
+ {
+ await setPhaseData(PHASE_FORCE_MERGE_ENABLED, e.target.checked);
+ }}
+ />
+
+
+
+ {phaseData[PHASE_FORCE_MERGE_ENABLED] ? (
+
+ {
+ await setPhaseData(PHASE_FORCE_MERGE_SEGMENTS, e.target.value);
+ }}
+ min={1}
+ />
+
+ ) : null}
+
+ ) : (
+
+
+ {
+ await setPhaseData(PHASE_ENABLED, true);
+ }}
+ >
+ Activate warm phase
+
+
+
+ )}
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.container.js
new file mode 100644
index 0000000000000..2f3ab4a14b37a
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.container.js
@@ -0,0 +1,43 @@
+/*
+ * 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 { connect } from 'react-redux';
+import { EditPolicy as PresentationComponent } from './edit_policy';
+import {
+ getSaveAsNewPolicy,
+ getSelectedPolicy,
+ getAffectedIndexTemplates,
+ validateLifecycle,
+ getLifecycle,
+ getPolicies,
+ isPolicyListLoaded,
+} from '../../store/selectors';
+import {
+ setSelectedPolicy,
+ setSelectedPolicyName,
+ setSaveAsNewPolicy,
+ saveLifecyclePolicy,
+ fetchPolicies,
+} from '../../store/actions';
+
+export const EditPolicy = connect(
+ state => ({
+ errors: validateLifecycle(state),
+ selectedPolicy: getSelectedPolicy(state),
+ affectedIndexTemplates: getAffectedIndexTemplates(state),
+ saveAsNewPolicy: getSaveAsNewPolicy(state),
+ lifecycle: getLifecycle(state),
+ policies: getPolicies(state),
+ isPolicyListLoaded: isPolicyListLoaded(state),
+ }),
+ {
+ setSelectedPolicy,
+ setSelectedPolicyName,
+ setSaveAsNewPolicy,
+ saveLifecyclePolicy,
+ fetchPolicies,
+ }
+)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
new file mode 100644
index 0000000000000..573fd98043285
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
@@ -0,0 +1,236 @@
+/*
+ * 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, { Component, Fragment } from 'react';
+import PropTypes from 'prop-types';
+import { toastNotifications } from 'ui/notify';
+import { goToPolicyList } from '../../services/navigation';
+
+import {
+ EuiPage,
+ EuiPageBody,
+ EuiFieldText,
+ EuiPageContent,
+ EuiFormRow,
+ EuiTitle,
+ EuiText,
+ EuiSpacer,
+ EuiSwitch,
+ EuiHorizontalRule,
+ EuiButton,
+ EuiButtonEmpty,
+} from '@elastic/eui';
+import { HotPhase } from './components/hot_phase';
+import { WarmPhase } from './components/warm_phase';
+import { DeletePhase } from './components/delete_phase';
+import { ColdPhase } from './components/cold_phase';
+import {
+ PHASE_HOT,
+ PHASE_COLD,
+ PHASE_DELETE,
+ PHASE_WARM,
+ STRUCTURE_POLICY_NAME,
+} from '../../store/constants';
+import { hasErrors } from '../../lib/find_errors';
+import { NodeAttrsDetails } from './components/node_attrs_details';
+import { ErrableFormRow } from './form_errors';
+
+export class EditPolicy extends Component {
+ static propTypes = {
+ selectedPolicy: PropTypes.string.isRequired,
+ errors: PropTypes.object.isRequired,
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ isShowingErrors: false,
+ isShowingNodeDetailsFlyout: false,
+ selectedNodeAttrsForDetails: undefined,
+ };
+ }
+ selectPolicy = policyName => {
+ const { setSelectedPolicy, policies } = this.props;
+ const selectedPolicy = policies.find(policy => {
+ return policy.name === policyName;
+ });
+ if (selectedPolicy) {
+ setSelectedPolicy(selectedPolicy);
+ }
+ };
+ componentDidMount() {
+ window.scrollTo(0, 0);
+ const {
+ match: {
+ params: { policyName },
+ },
+ isPolicyListLoaded,
+ fetchPolicies,
+ } = this.props;
+ if (policyName) {
+ if (isPolicyListLoaded) {
+ this.selectPolicy(policyName);
+ } else {
+ fetchPolicies(true, () => {
+ this.selectPolicy(policyName);
+ });
+ }
+ }
+ }
+ backToPolicyList = () => {
+ this.props.setSelectedPolicy(null);
+ goToPolicyList();
+ }
+ submit = async () => {
+ this.setState({ isShowingErrors: true });
+ const {
+ errors,
+ saveLifecyclePolicy,
+ lifecycle,
+ saveAsNewPolicy,
+ } = this.props;
+ if (hasErrors(errors)) {
+ toastNotifications.addDanger('Please the fix errors on the page');
+ } else {
+ const success = await saveLifecyclePolicy(lifecycle, saveAsNewPolicy);
+ if (success) {
+ this.backToPolicyList();
+ }
+ }
+ };
+
+ showNodeDetailsFlyout = selectedNodeAttrsForDetails => {
+ this.setState({ isShowingNodeDetailsFlyout: true, selectedNodeAttrsForDetails });
+ };
+ render() {
+ const {
+ selectedPolicy,
+ errors,
+ match: {
+ params: { policyName },
+ },
+ setSaveAsNewPolicy,
+ saveAsNewPolicy,
+ setSelectedPolicyName,
+ } = this.props;
+ const selectedPolicyName = selectedPolicy.name;
+ const { isShowingErrors } = this.state;
+
+ return (
+
+
+
+
+
+ {!selectedPolicyName
+ ? 'Create a lifecycle policy'
+ : `Edit lifecycle policy ${selectedPolicyName}`}
+
+
+
+
+
+ Configure the phases of your data and when to transition between them.
+
+
+
+ {policyName ? (
+
+
+
+
+ You are editing an existing policy. Any changes you make
+ will also change index templates that this policy is attached to.
+ Alternately, you can save these changes in a new policy and only change
+ the index template you selected.
+
+
+
+
+ {policyName ? (
+
+ {
+ await setSaveAsNewPolicy(e.target.checked);
+ }}
+ label={
+
+ Save this as a new policy
+
+ }
+ />
+
+ ) : null}
+
+ ) : null}
+ {saveAsNewPolicy || !policyName ? (
+
+
+ {
+ await setSelectedPolicyName(e.target.value);
+ }}
+ />
+
+
+ ) : null}
+
+
+
+
+
+
+
+
+
+
+
+ Back
+
+
+
+ Save your policy
+
+ {this.state.isShowingNodeDetailsFlyout ? (
+
this.setState({ isShowingNodeDetailsFlyout: false })}
+ />
+ ) : null}
+
+
+
+
+ );
+ }
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/form_errors.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/form_errors.js
new file mode 100644
index 0000000000000..fc3c29c4beb0c
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/form_errors.js
@@ -0,0 +1,36 @@
+/*
+ * 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, { cloneElement, Children, Fragment } from 'react';
+import { EuiFormRow } from '@elastic/eui';
+
+export const ErrableFormRow = ({
+ errorKey,
+ isShowingErrors,
+ errors,
+ children,
+ ...rest
+}) => {
+ return (
+ 0
+ }
+ error={errors[errorKey]}
+ {...rest}
+ >
+
+ {Children.map(children, child => cloneElement(child, {
+ isInvalid: isShowingErrors && errors[errorKey].length > 0,
+ }))}
+
+
+ );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/index.js
new file mode 100644
index 0000000000000..e4154a76289b6
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/index.js
@@ -0,0 +1,7 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { EditPolicy } from './edit_policy.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js
index 33e8b3f6cf91e..f14d3249f890b 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js
@@ -9,6 +9,7 @@ import moment from 'moment-timezone';
import { i18n } from '@kbn/i18n';
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
import { NoMatch } from '../no_match';
+import { BASE_PATH } from '../../../../../common/constants';
import {
EuiButton,
EuiLink,
@@ -170,9 +171,7 @@ export class PolicyTableUi extends Component {
{
-
- }}
+ href={`#${BASE_PATH}policies/edit/${value}`}
>
{value}
@@ -317,6 +316,14 @@ export class PolicyTableUi extends Component {
aria-label="Search policies"
/>
+
+
+ Create new policy
+
+
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js
index 06287ed7160b9..f03c0018034a5 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/lifecycle.js
@@ -4,24 +4,19 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { createAction } from 'redux-actions';
import { toastNotifications } from 'ui/notify';
import { saveLifecycle as saveLifecycleApi } from '../../api';
-export const savedLifecycle = createAction('SAVED_LIFECYCLE');
-export const saveLifecycle = (lifecycle, indexTemplatePatch) => async dispatch => {
- let saved;
+export const saveLifecyclePolicy = (lifecycle, isNew) => async () => {
try {
- saved = await saveLifecycleApi(lifecycle, indexTemplatePatch);
+ await saveLifecycleApi(lifecycle);
}
catch (err) {
toastNotifications.addDanger(err.data.message);
return false;
}
-
- toastNotifications.addSuccess(`Successfully created lifecycle policy '${lifecycle.name}'`);
-
- dispatch(savedLifecycle(saved));
+ const verb = isNew ? 'created' : 'updated';
+ toastNotifications.addSuccess(`Successfully ${verb} lifecycle policy '${lifecycle.name}'`);
return true;
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js
index 8f31e0deb3814..926b524921481 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/policies.js
@@ -22,7 +22,7 @@ export const policyPageChanged = createAction('POLICY_PAGE_CHANGED');
export const policySortDirectionChanged = createAction('POLICY_SORT_DIRECTION_CHANGED');
export const policyFilterChanged = createAction('POLICY_FILTER_CHANGED');
-export const fetchPolicies = (withIndices) => async dispatch => {
+export const fetchPolicies = (withIndices, callback) => async dispatch => {
let policies;
try {
policies = await loadPolicies(withIndices);
@@ -35,6 +35,7 @@ export const fetchPolicies = (withIndices) => async dispatch => {
if (policies.length === 0) {
dispatch(setSelectedPolicy());
}
+ callback && callback();
return policies;
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/constants.js b/x-pack/plugins/index_lifecycle_management/public/store/constants.js
index 748a4843e20af..873e4acd72312 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/constants.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/constants.js
@@ -61,50 +61,34 @@ export const STRUCTURE_INDEX_NAME = 'indexName';
export const STRUCTURE_ALIAS_NAME = 'aliasName';
export const ERROR_STRUCTURE = {
- [STRUCTURE_INDEX_TEMPLATE]: {
- [STRUCTURE_TEMPLATE_SELECTION]: {
- [STRUCTURE_TEMPLATE_NAME]: [],
- [STRUCTURE_INDEX_NAME]: [],
- [STRUCTURE_ALIAS_NAME]: []
- },
- [STRUCTURE_CONFIGURATION]: {
- [STRUCTURE_NODE_ATTRS]: [],
- [STRUCTURE_PRIMARY_NODES]: [],
- [STRUCTURE_REPLICAS]: []
- }
+ [PHASE_HOT]: {
+ [PHASE_ROLLOVER_ALIAS]: [],
+ [PHASE_ROLLOVER_MAX_AGE]: [],
+ [PHASE_ROLLOVER_MAX_AGE_UNITS]: [],
+ [PHASE_ROLLOVER_MAX_SIZE_STORED]: [],
+ [PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS]: [],
+ [PHASE_ROLLOVER_MAX_DOC_SIZE]: []
},
- [STRUCTURE_POLICY_CONFIGURATION]: {
- [PHASE_HOT]: {
- [PHASE_ROLLOVER_ALIAS]: [],
- [PHASE_ROLLOVER_MAX_AGE]: [],
- [PHASE_ROLLOVER_MAX_AGE_UNITS]: [],
- [PHASE_ROLLOVER_MAX_SIZE_STORED]: [],
- [PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS]: [],
- [PHASE_ROLLOVER_MAX_DOC_SIZE]: []
- },
- [PHASE_WARM]: {
- [PHASE_ROLLOVER_ALIAS]: [],
- [PHASE_ROLLOVER_MINIMUM_AGE]: [],
- [PHASE_ROLLOVER_MINIMUM_AGE_UNITS]: [],
- [PHASE_NODE_ATTRS]: [],
- [PHASE_PRIMARY_SHARD_COUNT]: [],
- [PHASE_REPLICA_COUNT]: [],
- [PHASE_FORCE_MERGE_SEGMENTS]: [],
- },
- [PHASE_COLD]: {
- [PHASE_ROLLOVER_ALIAS]: [],
- [PHASE_ROLLOVER_MINIMUM_AGE]: [],
- [PHASE_ROLLOVER_MINIMUM_AGE_UNITS]: [],
- [PHASE_NODE_ATTRS]: [],
- [PHASE_REPLICA_COUNT]: [],
- },
- [PHASE_DELETE]: {
- [PHASE_ROLLOVER_ALIAS]: [],
- [PHASE_ROLLOVER_MINIMUM_AGE]: [],
- [PHASE_ROLLOVER_MINIMUM_AGE_UNITS]: [],
- },
+ [PHASE_WARM]: {
+ [PHASE_ROLLOVER_ALIAS]: [],
+ [PHASE_ROLLOVER_MINIMUM_AGE]: [],
+ [PHASE_ROLLOVER_MINIMUM_AGE_UNITS]: [],
+ [PHASE_NODE_ATTRS]: [],
+ [PHASE_PRIMARY_SHARD_COUNT]: [],
+ [PHASE_REPLICA_COUNT]: [],
+ [PHASE_FORCE_MERGE_SEGMENTS]: [],
},
- [STRUCTURE_REVIEW]: {
- [STRUCTURE_POLICY_NAME]: [],
- }
+ [PHASE_COLD]: {
+ [PHASE_ROLLOVER_ALIAS]: [],
+ [PHASE_ROLLOVER_MINIMUM_AGE]: [],
+ [PHASE_ROLLOVER_MINIMUM_AGE_UNITS]: [],
+ [PHASE_NODE_ATTRS]: [],
+ [PHASE_REPLICA_COUNT]: [],
+ },
+ [PHASE_DELETE]: {
+ [PHASE_ROLLOVER_ALIAS]: [],
+ [PHASE_ROLLOVER_MINIMUM_AGE]: [],
+ [PHASE_ROLLOVER_MINIMUM_AGE_UNITS]: [],
+ },
+ [STRUCTURE_POLICY_NAME]: [],
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/middleware/auto_enable_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/middleware/auto_enable_phase.js
deleted file mode 100644
index d7d390f608ccf..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/store/middleware/auto_enable_phase.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { setPhaseData } from '../actions';
-import { getPhaseData } from '../selectors';
-import { SET_PHASE_DATA, PHASE_ENABLED } from '../constants';
-
-const setsPerPhase = {};
-
-export const autoEnablePhase = store => next => action => {
- const state = store.getState();
-
- if (action.type === SET_PHASE_DATA) {
- const { phase } = action.payload;
- setsPerPhase[phase] = setsPerPhase[phase] || 0;
- setsPerPhase[phase]++;
-
- if (setsPerPhase[phase] === 1 && !getPhaseData(state, phase, PHASE_ENABLED)) {
- store.dispatch(setPhaseData(phase, PHASE_ENABLED, true));
- }
- }
-
- return next(action);
-};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/middleware/auto_set_node_attrs.js b/x-pack/plugins/index_lifecycle_management/public/store/middleware/auto_set_node_attrs.js
deleted file mode 100644
index 5d59ccd8c4fe7..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/store/middleware/auto_set_node_attrs.js
+++ /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 { setPhaseData } from '../actions';
-import { getPhaseData } from '../selectors';
-import {
- SET_SELECTED_NODE_ATTRS,
- SET_PHASE_DATA,
- PHASE_WARM,
- PHASE_NODE_ATTRS,
- PHASE_COLD,
-} from '../constants';
-
-export const autoSetNodeAttrs = store => next => action => {
- const state = store.getState();
-
- if (action.type === SET_SELECTED_NODE_ATTRS) {
- const warmPhaseAttrs = getPhaseData(state, PHASE_WARM, PHASE_NODE_ATTRS);
- if (!warmPhaseAttrs) {
- store.dispatch(setPhaseData(PHASE_WARM, PHASE_NODE_ATTRS, action.payload));
- }
- } else if (action.type === SET_PHASE_DATA) {
- const { phase, key, value } = action.payload;
-
- if (phase === PHASE_WARM && key === PHASE_NODE_ATTRS) {
- const coldPhaseAttrs = getPhaseData(state, PHASE_COLD, PHASE_NODE_ATTRS);
- if (!coldPhaseAttrs) {
- store.dispatch(setPhaseData(PHASE_COLD, PHASE_NODE_ATTRS, value));
- }
- }
- }
-
- return next(action);
-};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/middleware/set_selected_policy_from_selected_template.js b/x-pack/plugins/index_lifecycle_management/public/store/middleware/set_selected_policy_from_selected_template.js
deleted file mode 100644
index a87f9c3496d64..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/store/middleware/set_selected_policy_from_selected_template.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import {
- fetchedIndexTemplate,
- fetchPolicies,
- setSelectedPolicy,
- setPhaseData
-} from '../actions';
-import { getSelectedNodeAttrs, getPhaseData } from '../selectors';
-import { PHASE_WARM, PHASE_NODE_ATTRS, PHASE_COLD } from '../constants';
-
-export const setSelectedPolicyFromSelectedTemplate = store => next => async action => {
- if (action.type === fetchedIndexTemplate().type) {
- const template = action.payload;
- if (template.settings.index && template.settings.index.lifecycle) {
- const policies = await fetchPolicies()(store.dispatch);
- const selectedPolicy = policies.find(policy => policy.name === template.settings.index.lifecycle.name);
- if (selectedPolicy) {
- store.dispatch(setSelectedPolicy(selectedPolicy));
-
- // We also want to update node attrs for future phases if they do not exist
- const state = store.getState();
- const hotNodeAttrs = getSelectedNodeAttrs(state);
- const warmNodeAttrs = getPhaseData(state, PHASE_WARM, PHASE_NODE_ATTRS);
- const coldNodeAttrs = getPhaseData(state, PHASE_COLD, PHASE_NODE_ATTRS);
-
- if (hotNodeAttrs && !warmNodeAttrs) {
- store.dispatch(setPhaseData(PHASE_WARM, PHASE_NODE_ATTRS, hotNodeAttrs));
- }
- if ((hotNodeAttrs || warmNodeAttrs) && !coldNodeAttrs) {
- store.dispatch(setPhaseData(PHASE_COLD, PHASE_NODE_ATTRS, warmNodeAttrs || hotNodeAttrs));
- }
- }
- }
- }
-
- return next(action);
-};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js
index bfeb72a6e50e8..27b5304fec1fa 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/reducers/policies.js
@@ -49,6 +49,7 @@ export const defaultPolicy = {
const defaultState = {
isLoading: false,
+ isLoaded: false,
originalPolicyName: undefined,
selectedPolicySet: false,
selectedPolicy: defaultPolicy,
@@ -68,6 +69,7 @@ export const policies = handleActions(
return {
...state,
isLoading: false,
+ isLoaded: true,
policies
};
},
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
index 640885e7056d8..cfd3d389a5628 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
@@ -13,21 +13,11 @@ import {
PHASE_ROLLOVER_ENABLED,
PHASE_ROLLOVER_MAX_AGE,
PHASE_ROLLOVER_MAX_SIZE_STORED,
- STRUCTURE_INDEX_TEMPLATE,
- STRUCTURE_CONFIGURATION,
- STRUCTURE_PRIMARY_NODES,
- STRUCTURE_REPLICAS,
- STRUCTURE_TEMPLATE_SELECTION,
- STRUCTURE_TEMPLATE_NAME,
STRUCTURE_POLICY_NAME,
- STRUCTURE_POLICY_CONFIGURATION,
- STRUCTURE_INDEX_NAME,
- STRUCTURE_ALIAS_NAME,
ERROR_STRUCTURE,
PHASE_ATTRIBUTES_THAT_ARE_NUMBERS,
PHASE_PRIMARY_SHARD_COUNT,
PHASE_SHRINK_ENABLED,
- STRUCTURE_REVIEW,
PHASE_FORCE_MERGE_ENABLED,
PHASE_FORCE_MERGE_SEGMENTS
} from '../constants';
@@ -36,23 +26,17 @@ import {
getPhases,
phaseToES,
getSelectedPolicyName,
- getSelectedIndexTemplateName,
- getFullSelectedIndexTemplate,
isNumber,
getSelectedPrimaryShardCount,
- getSelectedReplicaCount,
getSaveAsNewPolicy,
getSelectedOriginalPolicyName,
- getBootstrapEnabled,
- getIndexName,
- getAliasName,
} from '.';
-export const validatePhase = (type, phase, state) => {
- const errors = {};
+export const validatePhase = (type, phase, errors) => {
+ const phaseErrors = {};
if (!phase[PHASE_ENABLED]) {
- return errors;
+ return;
}
if (phase[PHASE_ROLLOVER_ENABLED]) {
@@ -60,10 +44,10 @@ export const validatePhase = (type, phase, state) => {
!isNumber(phase[PHASE_ROLLOVER_MAX_AGE]) &&
!isNumber(phase[PHASE_ROLLOVER_MAX_SIZE_STORED])
) {
- errors[PHASE_ROLLOVER_MAX_AGE] = [
+ phaseErrors[PHASE_ROLLOVER_MAX_AGE] = [
'A maximum age is required'
];
- errors[PHASE_ROLLOVER_MAX_SIZE_STORED] = [
+ phaseErrors[PHASE_ROLLOVER_MAX_SIZE_STORED] = [
'A maximum index size is required'
];
}
@@ -76,93 +60,56 @@ export const validatePhase = (type, phase, state) => {
continue;
}
if (!isNumber(phase[numberedAttribute])) {
- errors[numberedAttribute] = ['A number is required'];
+ phaseErrors[numberedAttribute] = ['A number is required'];
}
else if (phase[numberedAttribute] < 0) {
- errors[numberedAttribute] = ['Only positive numbers are allowed'];
+ phaseErrors[numberedAttribute] = ['Only positive numbers are allowed'];
}
else if (numberedAttribute === PHASE_PRIMARY_SHARD_COUNT && phase[numberedAttribute] < 1) {
- errors[numberedAttribute] = ['Only positive numbers are allowed'];
+ phaseErrors[numberedAttribute] = ['Only positive numbers are allowed'];
}
}
}
if (phase[PHASE_SHRINK_ENABLED]) {
- const selectedTemplate = getFullSelectedIndexTemplate(state);
- // shrink options not shown in GUI for primary shard count of 1, so don't validate
- if (selectedTemplate && selectedTemplate.settings.number_of_shards > 1) {
- if (!isNumber(phase[PHASE_PRIMARY_SHARD_COUNT])) {
- errors[PHASE_PRIMARY_SHARD_COUNT] = ['A number is required.'];
- }
- else if (phase[PHASE_PRIMARY_SHARD_COUNT] < 1) {
- errors[PHASE_PRIMARY_SHARD_COUNT] = ['Only positive numbers above 0 are allowed.'];
- }
+ if (!isNumber(phase[PHASE_PRIMARY_SHARD_COUNT])) {
+ phaseErrors[PHASE_PRIMARY_SHARD_COUNT] = ['A number is required.'];
+ }
+ else if (phase[PHASE_PRIMARY_SHARD_COUNT] < 1) {
+ phaseErrors[PHASE_PRIMARY_SHARD_COUNT] = ['Only positive numbers are allowed.'];
}
}
if (phase[PHASE_FORCE_MERGE_ENABLED]) {
if (!isNumber(phase[PHASE_FORCE_MERGE_SEGMENTS])) {
- errors[PHASE_FORCE_MERGE_SEGMENTS] = ['A number is required.'];
+ phaseErrors[PHASE_FORCE_MERGE_SEGMENTS] = ['A number is required.'];
}
else if (phase[PHASE_FORCE_MERGE_SEGMENTS] < 1) {
- errors[PHASE_FORCE_MERGE_SEGMENTS] = ['Only positive numbers above 0 are allowed.'];
+ phaseErrors[PHASE_FORCE_MERGE_SEGMENTS] = ['Only positive numbers above 0 are allowed.'];
}
}
-
- return errors;
+ errors[type] = {
+ ...errors[type],
+ ...phaseErrors
+ };
};
export const validateLifecycle = state => {
// This method of deep copy does not always work but it should be fine here
const errors = JSON.parse(JSON.stringify(ERROR_STRUCTURE));
- if (!getSelectedIndexTemplateName(state)) {
- errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][
- STRUCTURE_TEMPLATE_NAME
- ].push('An index template is required');
- }
-
- if (getBootstrapEnabled(state) && !getIndexName(state)) {
- errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][STRUCTURE_INDEX_NAME].push('An index name is required');
- }
-
- if (!getAliasName(state)) {
- errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][STRUCTURE_ALIAS_NAME].push('A write alias name is required');
- }
-
- if (!isNumber(getSelectedPrimaryShardCount(state))) {
- errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][
- STRUCTURE_PRIMARY_NODES
- ].push('A value is required');
- }
- else if (getSelectedPrimaryShardCount(state) < 1) {
- errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][
- STRUCTURE_PRIMARY_NODES
- ].push('Only positive numbers are allowed');
- }
-
- if (!isNumber(getSelectedReplicaCount(state))) {
- errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][
- STRUCTURE_REPLICAS
- ].push('A value is required');
- }
- else if (getSelectedReplicaCount(state) < 0) {
- errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][
- STRUCTURE_REPLICAS
- ].push('Only positive numbers are allowed');
- }
if (!getSelectedPolicyName(state)) {
- errors[STRUCTURE_REVIEW][STRUCTURE_POLICY_NAME].push('A policy name is required');
+ errors[STRUCTURE_POLICY_NAME].push('A policy name is required');
}
if (getSaveAsNewPolicy(state) && getSelectedOriginalPolicyName(state) === getSelectedPolicyName(state)) {
- errors[STRUCTURE_REVIEW][STRUCTURE_POLICY_NAME].push('The policy name must be different');
+ errors[STRUCTURE_POLICY_NAME].push('The policy name must be different');
}
// if (getSaveAsNewPolicy(state)) {
// const policyNames = getAllPolicyNamesFromTemplates(state);
// if (policyNames.includes(getSelectedPolicyName(state))) {
- // errors[STRUCTURE_POLICY_CONFIGURATION][STRUCTURE_POLICY_NAME].push('That policy name is already used.');
+ // errors[STRUCTURE_POLICY_NAME].push('That policy name is already used.');
// }
// }
@@ -171,33 +118,19 @@ export const validateLifecycle = state => {
const coldPhase = getPhase(state, PHASE_COLD);
const deletePhase = getPhase(state, PHASE_DELETE);
- errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_HOT] = {
- ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_HOT],
- ...validatePhase(PHASE_HOT, hotPhase)
- };
- errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_WARM] = {
- ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_WARM],
- ...validatePhase(PHASE_WARM, warmPhase, state)
- };
- errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_COLD] = {
- ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_COLD],
- ...validatePhase(PHASE_COLD, coldPhase)
- };
- errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_DELETE] = {
- ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_DELETE],
- ...validatePhase(PHASE_DELETE, deletePhase)
- };
-
+ validatePhase(PHASE_HOT, hotPhase, errors);
+ validatePhase(PHASE_WARM, warmPhase, errors);
+ validatePhase(PHASE_COLD, coldPhase, errors);
+ validatePhase(PHASE_DELETE, deletePhase, errors);
if (warmPhase[PHASE_SHRINK_ENABLED]) {
if (isNumber(warmPhase[PHASE_PRIMARY_SHARD_COUNT]) && warmPhase[PHASE_PRIMARY_SHARD_COUNT] > 0) {
if (getSelectedPrimaryShardCount(state) % warmPhase[PHASE_PRIMARY_SHARD_COUNT] !== 0) {
- errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_WARM][PHASE_PRIMARY_SHARD_COUNT].push(
+ errors[PHASE_WARM][PHASE_PRIMARY_SHARD_COUNT].push(
'The shard count needs to be a divisor of the hot phase shard count.'
);
}
}
}
-
return errors;
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
index b4b7e72545c36..9cf603c071faf 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
@@ -43,7 +43,6 @@ import { filterItems, sortTable } from '../../services';
export const getPolicies = state => state.policies.policies;
export const getIsNewPolicy = state => state.policies.selectedPolicy.isNew;
-
export const getSelectedPolicy = state => state.policies.selectedPolicy;
export const getIsSelectedPolicySet = state => state.policies.selectedPolicySet;
export const getSelectedOriginalPolicyName = state => state.policies.originalPolicyName;
@@ -51,6 +50,7 @@ export const getPolicyFilter = (state) => state.policies.filter;
export const getPolicySort = (state) => state.policies.sort;
export const getPolicyCurrentPage = (state) => state.policies.currentPage;
export const getPolicyPageSize = (state) => state.policies.pageSize;
+export const isPolicyListLoaded = (state) => state.policies.isLoaded;
const getFilteredPolicies = createSelector(
getPolicies,
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/store.js b/x-pack/plugins/index_lifecycle_management/public/store/store.js
index 2e3b5c219dad8..151a7a5bf8b50 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/store.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/store.js
@@ -14,14 +14,10 @@ import thunk from 'redux-thunk';
import {
indexLifecycleManagement
} from './reducers/';
-import {
- autoEnablePhase,
- setSelectedPolicyFromSelectedTemplate,
- autoSetNodeAttrs
-} from './middleware';
+
export const indexLifecycleManagementStore = (initialState = {}) => {
- const enhancers = [applyMiddleware(thunk, autoEnablePhase, setSelectedPolicyFromSelectedTemplate, autoSetNodeAttrs)];
+ const enhancers = [applyMiddleware(thunk)];
window.__REDUX_DEVTOOLS_EXTENSION__ && enhancers.push(window.__REDUX_DEVTOOLS_EXTENSION__());
return createStore(
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_create_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_create_route.js
index 14cf049454a34..ca1a021c6100a 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_create_route.js
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_create_route.js
@@ -11,7 +11,6 @@ import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
import { isEsErrorFactory } from '../../../lib/is_es_error_factory';
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory';
-import { merge } from 'lodash';
async function createLifecycle(callWithRequest, lifecycle) {
const body = {
@@ -29,44 +28,6 @@ async function createLifecycle(callWithRequest, lifecycle) {
return await callWithRequest('transport.request', params);
}
-async function getIndexTemplate(callWithRequest, indexTemplate) {
- const response = await callWithRequest('indices.getTemplate', { name: indexTemplate });
- return response[indexTemplate];
-}
-
-async function updateIndexTemplate(callWithRequest, indexTemplatePatch) {
- // Fetch existing template
- const template = await getIndexTemplate(callWithRequest, indexTemplatePatch.indexTemplate);
- merge(template, {
- settings: {
- index: {
- number_of_shards: indexTemplatePatch.primaryShardCount,
- number_of_replicas: indexTemplatePatch.replicaCount,
- lifecycle: {
- name: indexTemplatePatch.lifecycleName,
- rollover_alias: indexTemplatePatch.rolloverAlias
- },
- routing: {
- allocation: {
- include: {
- sattr_name: indexTemplatePatch.nodeAttrs,
- }
- }
- }
- }
- }
- });
-
- const params = {
- method: 'PUT',
- path: `/_template/${indexTemplatePatch.indexTemplate}`,
- ignore: [ 404 ],
- body: template,
- };
-
- return await callWithRequest('transport.request', params);
-}
-
export function registerCreateRoute(server) {
const isEsError = isEsErrorFactory(server);
const licensePreRouting = licensePreRoutingFactory(server);
@@ -79,8 +40,7 @@ export function registerCreateRoute(server) {
try {
const response = await createLifecycle(callWithRequest, request.payload.lifecycle);
- const response2 = await updateIndexTemplate(callWithRequest, request.payload.indexTemplatePatch);
- reply([response, response2]);
+ reply(response);
} catch (err) {
if (isEsError(err)) {
return reply(wrapEsError(err));
From 71543748da9a9c01398432fdc6bfee7ad07f6b79 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Thu, 25 Oct 2018 15:31:04 -0400
Subject: [PATCH 073/102] simplified delete
---
.../public/api/index.js | 4 +-
.../components/policy_table/confirm_delete.js | 42 ++----
.../components/policy_table/policy_table.js | 133 +++++-------------
3 files changed, 49 insertions(+), 130 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/api/index.js b/x-pack/plugins/index_lifecycle_management/public/api/index.js
index 683ba29a2dbb2..542acfe8e987b 100644
--- a/x-pack/plugins/index_lifecycle_management/public/api/index.js
+++ b/x-pack/plugins/index_lifecycle_management/public/api/index.js
@@ -39,8 +39,8 @@ export async function loadPolicies(withIndices) {
return response.data;
}
-export async function deletePolicies(policyNames) {
- const response = await httpClient.delete(`${apiPrefix}/policies/${policyNames.join(',')}`);
+export async function deletePolicy(policyName) {
+ const response = await httpClient.delete(`${apiPrefix}/policies/${policyName}`);
return response.data;
}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/confirm_delete.js b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/confirm_delete.js
index 3b20042c7f3a4..9b3e250d6f958 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/confirm_delete.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/confirm_delete.js
@@ -4,60 +4,40 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Component, Fragment } from 'react';
+import React, { Component } from 'react';
import { EuiOverlayMask, EuiConfirmModal } from '@elastic/eui';
import { toastNotifications } from 'ui/notify';
-import { deletePolicies } from '../../../../api';
+import { deletePolicy } from '../../../../api';
export class ConfirmDelete extends Component {
- deletePolicies = async () => {
- const { policiesToDelete, callback } = this.props;
- const policyNames = policiesToDelete.map(policy => {
- return policy.name;
- });
+ deletePolicy = async () => {
+ const { policyToDelete, callback } = this.props;
+ const policyName = policyToDelete.name;
try {
- await deletePolicies(policyNames);
- toastNotifications.addSuccess(`Deleted policies ${policyNames.join(', ')}`);
+ await deletePolicy(policyName);
+ toastNotifications.addSuccess(`Deleted policy ${policyName}`);
} catch (e) {
- toastNotifications.addDanger(`Error deleting policies ${policyNames.join(', ')}`);
+ toastNotifications.addDanger(`Error deleting policy ${policyName}`);
}
if (callback) {
callback();
}
};
render() {
- const { policiesToDelete, onCancel } = this.props;
- const moreThanOne = policiesToDelete.length > 1;
- const title = moreThanOne
- ? `Delete ${policiesToDelete.length} policies`
- : `Delete policy '${policiesToDelete[0].name}'`;
+ const { policyToDelete, onCancel } = this.props;
+ const title = `Delete policy '${policyToDelete.name}'`;
return (
{}}
>
-
-
- You are about to delete {moreThanOne ? 'these' : 'this'} polic
- {moreThanOne ? 'ies' : 'y'}:
-
-
- {policiesToDelete.map(
- (({ name, coveredIndices }) => (
- -
- {name} {coveredIndices ? `: ${coveredIndices.join(',')}` : null}
-
- ): null)
- )}
-
-
This operation cannot be undone.
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js
index f14d3249f890b..1ed6d7ab44863 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js
@@ -13,7 +13,7 @@ import { BASE_PATH } from '../../../../../common/constants';
import {
EuiButton,
EuiLink,
- EuiCheckbox,
+ EuiButtonIcon,
EuiFieldSearch,
EuiFlexGroup,
EuiFlexItem,
@@ -23,11 +23,9 @@ import {
EuiTableBody,
EuiTableHeader,
EuiTableHeaderCell,
- EuiTableHeaderCellCheckbox,
EuiTablePagination,
EuiTableRow,
EuiTableRowCell,
- EuiTableRowCellCheckbox,
EuiTitle,
EuiText,
EuiPageBody,
@@ -51,24 +49,6 @@ const HEADERS = {
};
export class PolicyTableUi extends Component {
- static getDerivedStateFromProps(props, state) {
- // Deselect any policies which no longer exist, e.g. they've been deleted.
- const { selectedPoliciesMap } = state;
- const policyNames = props.policies.map(policy => policy.name);
- const selectedPolicyNames = Object.keys(selectedPoliciesMap);
- const missingPolicyNames = selectedPolicyNames.filter(selectedpolicyName => {
- return !policyNames.includes(selectedpolicyName);
- });
-
- if (missingPolicyNames.length) {
- const newMap = { ...selectedPoliciesMap };
- missingPolicyNames.forEach(missingPolicyName => delete newMap[missingPolicyName]);
- return { selectedPoliciesMap: newMap };
- }
-
- return null;
- }
-
constructor(props) {
super(props);
@@ -81,19 +61,21 @@ export class PolicyTableUi extends Component {
this.props.fetchPolicies(true);
}
deleteConfirmation() {
- if (!this.state.showDeleteConfirmation) {
+ const { policyToDelete } = this.state;
+ if (!policyToDelete) {
return null;
}
return (
this.setState({ policyToDelete: null })}
/>
);
}
handleDelete = () => {
this.props.fetchPolicies(true);
- this.setState({ showDeleteConfirmation: false });
+ this.setState({ policyToDelete: null });
}
onSort = column => {
const { sortField, isSortAscending, policySortChanged } = this.props;
@@ -101,54 +83,9 @@ export class PolicyTableUi extends Component {
policySortChanged(column, newIsSortAscending);
};
- toggleAll = () => {
- const allSelected = this.areAllItemsSelected();
- if (allSelected) {
- return this.setState({ selectedPoliciesMap: {} });
- }
- const { policies } = this.props;
- const selectedPoliciesMap = {};
- policies.forEach(({ name }) => {
- selectedPoliciesMap[name] = true;
- });
- this.setState({
- selectedPoliciesMap
- });
- };
-
- toggleItem = name => {
- this.setState(({ selectedPoliciesMap }) => {
- const newMap = { ...selectedPoliciesMap };
- if (newMap[name]) {
- delete newMap[name];
- } else {
- newMap[name] = true;
- }
- return {
- selectedPoliciesMap: newMap
- };
- });
- };
-
- isItemSelected = name => {
- return !!this.state.selectedPoliciesMap[name];
- };
- getSelectedPolicies() {
- return this.props.policies.filter(({ name }) => {
- return this.isItemSelected(name);
- });
- }
- areAllItemsSelected = () => {
- const { policies } = this.props;
- const unselectedItem = policies.find(
- policy => !this.isItemSelected(policy.name)
- );
- return !unselectedItem;
- };
-
buildHeader() {
const { sortField, isSortAscending } = this.props;
- return Object.entries(HEADERS).map(([fieldName, label]) => {
+ const headers = Object.entries(HEADERS).map(([fieldName, label]) => {
const isSorted = sortField === fieldName;
return (
);
});
+ headers.push(
+
+ );
+ return headers;
}
buildRowCell(fieldName, value) {
@@ -189,8 +134,8 @@ export class PolicyTableUi extends Component {
}
buildRowCells(policy) {
- return Object.keys(HEADERS).map(fieldName => {
- const { name } = policy;
+ const { name } = policy;
+ const cells = Object.keys(HEADERS).map(fieldName => {
const value = policy[fieldName];
return (
);
});
+ cells.push(
+
+ this.setState({ policyToDelete: policy })}
+ iconType="trash"
+ />
+
+ );
+ return cells;
}
buildRows() {
- const { policies = [], detailPanelpolicyName } = this.props;
+ const { policies = [] } = this.props;
return policies.map(policy => {
const { name } = policy;
return (
-
- {
- this.toggleItem(name);
- }}
- data-test-subj="policyTableRowCheckbox"
- />
-
{this.buildRowCells(policy)}
);
@@ -271,7 +218,7 @@ export class PolicyTableUi extends Component {
@@ -280,7 +227,7 @@ export class PolicyTableUi extends Component {
@@ -331,14 +278,6 @@ export class PolicyTableUi extends Component {
{policies.length > 0 ? (
-
-
-
{this.buildHeader()}
{this.buildRows()}
From d0a45ae37e1b3c911fd4c4b28ab012dcc2f3273d Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Thu, 25 Oct 2018 15:34:38 -0400
Subject: [PATCH 074/102] cleanup edit_policy
---
.../public/sections/edit_policy/edit_policy.js | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
index 573fd98043285..5cf7026f7bd55 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
@@ -40,7 +40,7 @@ import { ErrableFormRow } from './form_errors';
export class EditPolicy extends Component {
static propTypes = {
- selectedPolicy: PropTypes.string.isRequired,
+ selectedPolicy: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired,
};
@@ -214,11 +214,11 @@ export class EditPolicy extends Component {
isShowingErrors={isShowingErrors && hasErrors(errors[PHASE_DELETE])}
/>
-
- Back
+
+ Cancel
-
+
Save your policy
{this.state.isShowingNodeDetailsFlyout ? (
From 450a993542205703c8d3b92b4a9c371fbf11412e Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Thu, 25 Oct 2018 15:36:14 -0400
Subject: [PATCH 075/102] removed wizard code
---
.../configuration/configuration.container.js | 41 --
.../components/configuration/configuration.js | 179 ---------
.../components/configuration/index.js | 7 -
.../components/template_selection/index.js | 7 -
.../template_selection.container.js | 41 --
.../template_selection/template_selection.js | 163 --------
.../wizard/components/index_template/index.js | 10 -
.../index_template/index_template.js | 83 ----
.../components/node_attrs_details/index.js | 7 -
.../node_attrs_details.container.js | 18 -
.../node_attrs_details/node_attrs_details.js | 80 ----
.../cold_phase/cold_phase.container.js | 34 --
.../components/cold_phase/cold_phase.js | 231 -----------
.../components/cold_phase/index.js | 7 -
.../delete_phase/delete_phase.container.js | 20 -
.../components/delete_phase/delete_phase.js | 158 --------
.../components/delete_phase/index.js | 7 -
.../hot_phase/hot_phase.container.js | 23 --
.../components/hot_phase/hot_phase.js | 210 ----------
.../components/hot_phase/index.js | 7 -
.../components/warm_phase/index.js | 7 -
.../warm_phase/warm_phase.container.js | 33 --
.../components/warm_phase/warm_phase.js | 371 ------------------
.../components/policy_configuration/index.js | 7 -
.../policy_configuration.container.js | 47 ---
.../policy_configuration.js | 177 ---------
.../components/policy_selection/index.js | 7 -
.../policy_selection.container.js | 30 --
.../policy_selection/policy_selection.js | 84 ----
.../wizard/components/review/diff_view.js | 107 -----
.../wizard/components/review/index.js | 7 -
.../components/review/review.container.js | 59 ---
.../wizard/components/review/review.js | 286 --------------
.../wizard/components/review/review.less | 7 -
.../public/sections/wizard/form_errors.js | 36 --
.../public/sections/wizard/index.js | 7 -
.../sections/wizard/wizard.container.js | 37 --
.../public/sections/wizard/wizard.js | 177 ---------
38 files changed, 2819 deletions(-)
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.container.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/index.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/index.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.container.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index_template.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/index.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/node_attrs_details.container.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/node_attrs_details.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.container.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/index.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.container.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/index.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.container.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/index.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/index.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.container.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/index.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.container.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/index.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.container.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/diff_view.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/index.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.container.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.less
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/form_errors.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/index.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.container.js
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.container.js
deleted file mode 100644
index 01ee20f34d5db..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.container.js
+++ /dev/null
@@ -1,41 +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 { connect } from 'react-redux';
-import { Configuration as PresentationComponent } from './configuration';
-import {
- getNodeOptions,
- getSelectedPrimaryShardCount,
- getSelectedReplicaCount,
- getSelectedNodeAttrs,
- getIsPrimaryShardCountHigherThanSelectedNodeAttrsCount,
-} from '../../../../../../store/selectors';
-import {
- setSelectedNodeAttrs,
- setSelectedPrimaryShardCount,
- setSelectedReplicaCount,
- fetchNodes
-} from '../../../../../../store/actions';
-
-export const Configuration = connect(
- state => ({
- nodeOptions: getNodeOptions(state),
- selectedNodeAttrs: getSelectedNodeAttrs(state),
- selectedPrimaryShardCount: getSelectedPrimaryShardCount(state),
- selectedReplicaCount: getSelectedReplicaCount(state),
- selectedNodeAttrs: getSelectedNodeAttrs(state),
- isPrimaryShardCountHigherThanSelectedNodeAttrsCount: getIsPrimaryShardCountHigherThanSelectedNodeAttrsCount(state),
- }),
- {
- setSelectedNodeAttrs,
- setSelectedPrimaryShardCount,
- setSelectedReplicaCount,
- fetchNodes
- }
-)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.js
deleted file mode 100644
index f1f1e28f3e6ec..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/configuration.js
+++ /dev/null
@@ -1,179 +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, { Component } from 'react';
-import PropTypes from 'prop-types';
-
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiSpacer,
- EuiSelect,
- EuiFieldNumber,
- EuiCallOut,
- EuiButtonEmpty,
- EuiDescribedFormGroup,
-} from '@elastic/eui';
-import { LearnMoreLink } from '../../../../../../components/learn_more_link';
-import {
- STRUCTURE_NODE_ATTRS,
- STRUCTURE_PRIMARY_NODES,
- STRUCTURE_REPLICAS,
-} from '../../../../../../store/constants';
-
-import { ErrableFormRow } from '../../../../form_errors';
-import { NodeAttrsDetails } from '../../../node_attrs_details';
-
-export class Configuration extends Component {
- static propTypes = {
- fetchNodes: PropTypes.func.isRequired,
- setSelectedNodeAttrs: PropTypes.func.isRequired,
- setSelectedPrimaryShardCount: PropTypes.func.isRequired,
- setSelectedReplicaCount: PropTypes.func.isRequired,
- validate: PropTypes.func.isRequired,
-
- selectedPrimaryShardCount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
- selectedNodeAttrs: PropTypes.string.isRequired,
- nodeOptions: PropTypes.array.isRequired,
- selectedReplicaCount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
- isShowingErrors: PropTypes.bool.isRequired,
- errors: PropTypes.object.isRequired,
- isPrimaryShardCountHigherThanSelectedNodeAttrsCount: PropTypes.bool.isRequired,
- };
-
- constructor(props) {
- super(props);
- this.state = {
- isShowingNodeDetailsFlyout: false,
- };
- }
-
- componentWillMount() {
- this.props.fetchNodes();
- }
-
- render() {
- const {
- setSelectedNodeAttrs,
- setSelectedPrimaryShardCount,
- setSelectedReplicaCount,
- validate,
-
- nodeOptions,
- selectedPrimaryShardCount,
- selectedReplicaCount,
- selectedNodeAttrs,
- errors,
- isShowingErrors,
- isPrimaryShardCountHigherThanSelectedNodeAttrsCount,
- } = this.props;
-
- const primaryNodeErrors = isPrimaryShardCountHigherThanSelectedNodeAttrsCount ? (
-
- The shard count should be lower than the number of nodes that match the selected attributes.
-
- ) : null;
-
- return (
-
- Configure hot indices}
- titleSize="s"
- description="A hot index is actively being written to."
- fullWidth
- >
- this.setState({ isShowingNodeDetailsFlyout: true })}
- >
- View a list of nodes attached to this configuration
-
- ) : null
- }
- >
- {
- await setSelectedNodeAttrs(e.target.value);
- validate();
- }}
- options={nodeOptions}
- />
-
-
- The best way to determine how many shards you need is to benchmark using realistic
- data and queries on your hardware.{' '}
-
-
- }
- />
-
-
-
-
- {
- await setSelectedPrimaryShardCount(e.target.value);
- validate();
- }}
- value={selectedPrimaryShardCount}
- min={1}
- />
-
-
-
-
- {
- await setSelectedReplicaCount(e.target.value);
- validate();
- }}
- value={selectedReplicaCount}
- min={0}
- />
-
-
-
- {this.state.isShowingNodeDetailsFlyout ? (
- this.setState({ isShowingNodeDetailsFlyout: false })}
- />
- ) : null}
-
- {primaryNodeErrors}
-
-
- );
- }
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/index.js
deleted file mode 100644
index 2a387bd853de8..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/configuration/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 { Configuration } from './configuration.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/index.js
deleted file mode 100644
index a7c5cfb8f3dab..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/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 { TemplateSelection } from './template_selection.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.container.js
deleted file mode 100644
index fb11120d37d3c..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.container.js
+++ /dev/null
@@ -1,41 +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 { connect } from 'react-redux';
-import { TemplateSelection as PresentationComponent } from './template_selection';
-import {
- getIndexTemplateOptions,
- getSelectedIndexTemplateName,
- getIndexName,
- getAliasName,
- getBootstrapEnabled,
- getSelectedIndexTemplateIndices,
-} from '../../../../../../store/selectors';
-import {
- fetchIndexTemplates,
- setSelectedIndexTemplate,
- setAliasName,
- setBootstrapEnabled,
- setIndexName
-} from '../../../../../../store/actions';
-
-export const TemplateSelection = connect(
- state => ({
- templateOptions: getIndexTemplateOptions(state),
- selectedIndexTemplateName: getSelectedIndexTemplateName(state),
- bootstrapEnabled: getBootstrapEnabled(state),
- aliasName: getAliasName(state),
- indexName: getIndexName(state),
- selectedIndexTemplateIndices: getSelectedIndexTemplateIndices(state),
- }),
- {
- fetchIndexTemplates,
- setSelectedIndexTemplate,
- setBootstrapEnabled,
- setIndexName,
- setAliasName,
- }
-)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.js
deleted file mode 100644
index c72cbdf641337..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/components/template_selection/template_selection.js
+++ /dev/null
@@ -1,163 +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, { Fragment, Component } from 'react';
-import PropTypes from 'prop-types';
-
-import {
- EuiSelect,
- EuiFormRow,
- EuiSwitch,
- EuiFieldText,
- EuiDescribedFormGroup,
- EuiSpacer,
-} from '@elastic/eui';
-
-import { LearnMoreLink } from '../../../../../../components/learn_more_link';
-import { ErrableFormRow } from '../../../../form_errors';
-import {
- STRUCTURE_TEMPLATE_NAME,
- STRUCTURE_INDEX_NAME,
- STRUCTURE_ALIAS_NAME,
-} from '../../../../../../store/constants';
-
-export class TemplateSelection extends Component {
- static propTypes = {
- fetchIndexTemplates: PropTypes.func.isRequired,
- setSelectedIndexTemplate: PropTypes.func.isRequired,
- validate: PropTypes.func.isRequired,
-
- selectedIndexTemplateName: PropTypes.string.isRequired,
- templateOptions: PropTypes.array.isRequired,
- errors: PropTypes.object.isRequired,
- isShowingErrors: PropTypes.bool.isRequired,
- };
-
- constructor(props) {
- super(props);
- this.state = {
- isIncludingSystemIndices: false,
- };
- }
-
- componentWillMount() {
- this.props.fetchIndexTemplates();
- }
-
- onChangeIncludingSystemIndices = e => {
- this.setState({ isIncludingSystemIndices: e.target.checked });
- };
-
- render() {
- const {
- setSelectedIndexTemplate,
- validate,
- setBootstrapEnabled,
- setIndexName,
- setAliasName,
-
- bootstrapEnabled,
- selectedIndexTemplateIndices,
- indexName,
- aliasName,
- selectedIndexTemplateName,
- errors,
- isShowingErrors,
- } = this.props;
-
- const { isIncludingSystemIndices } = this.state;
-
- const templateOptions = this.props.templateOptions.filter(option => {
- if (option.value && option.value.startsWith('.') && !isIncludingSystemIndices) {
- return false;
- }
- return true;
- });
-
- return (
- Select an index template}
- fullWidth
- titleSize="s"
- description={
-
- An index template defines the settings, mappings, and aliases to apply
- when you create an index.{' '}
-
-
- }
- >
-
-
-
- {
- await setSelectedIndexTemplate(e.target.value);
- validate();
- }}
- options={templateOptions}
- />
-
-
- {
- await setAliasName(e.target.value);
- validate();
- }}
- />
-
- {selectedIndexTemplateName && selectedIndexTemplateIndices.length === 0 ? (
-
-
- setBootstrapEnabled(e.target.checked)}
- label={Create an index with this index template}
- />
-
- {bootstrapEnabled ? (
-
-
- {
- await setIndexName(e.target.value);
- validate();
- }}
- />
-
-
- ) : null}
-
- ) : null}
-
- );
- }
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index.js
deleted file mode 100644
index 20271f5f66ec2..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index.js
+++ /dev/null
@@ -1,10 +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 { IndexTemplate } from './index_template';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index_template.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index_template.js
deleted file mode 100644
index 70566e84867df..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/index_template/index_template.js
+++ /dev/null
@@ -1,83 +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, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { toastNotifications } from 'ui/notify';
-
-import { TemplateSelection } from './components/template_selection';
-import { Configuration } from './components/configuration';
-
-import {
- EuiHorizontalRule,
- EuiButton,
-} from '@elastic/eui';
-import { hasErrors } from '../../../../lib/find_errors';
-import {
- STRUCTURE_TEMPLATE_SELECTION,
- STRUCTURE_CONFIGURATION,
-} from '../../../../store/constants';
-
-export class IndexTemplate extends Component {
- static propTypes = {
- done: PropTypes.func.isRequired,
-
- errors: PropTypes.object,
- };
-
- constructor(props) {
- super(props);
- this.state = {
- isShowingErrors: false,
- };
- }
-
- validate = async () => {
- await this.props.validate();
- const noErrors = !hasErrors(this.props.errors);
- return noErrors;
- };
-
- submit = async () => {
- this.setState({ isShowingErrors: true });
- if (await this.validate()) {
- this.props.done();
- } else {
- toastNotifications.addDanger('Please fix the errors on the page');
- }
- };
-
- render() {
- const { errors } = this.props;
- const { isShowingErrors } = this.state;
-
- return (
-
-
-
-
-
-
-
- Continue
-
-
- );
- }
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/index.js
deleted file mode 100644
index 885e965c46c4b..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/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 { NodeAttrsDetails } from './node_attrs_details.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/node_attrs_details.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/node_attrs_details.container.js
deleted file mode 100644
index 3128a38c2c34f..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/node_attrs_details.container.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import { connect } from 'react-redux';
-import { NodeAttrsDetails as PresentationComponent } from './node_attrs_details';
-import { getNodeDetails, getExistingAllocationRules } from '../../../../store/selectors';
-import { fetchNodeDetails } from '../../../../store/actions';
-
-export const NodeAttrsDetails = connect(
- (state, ownProps) => ({
- details: getNodeDetails(state, ownProps.selectedNodeAttrs),
- allocationRules: getExistingAllocationRules(state),
- }),
- { fetchNodeDetails }
-)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/node_attrs_details.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/node_attrs_details.js
deleted file mode 100644
index 7cb2977e706ab..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/node_attrs_details.js
+++ /dev/null
@@ -1,80 +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, { Fragment, PureComponent } from 'react';
-import PropTypes from 'prop-types';
-
-import {
- EuiFlyoutBody,
- EuiFlyoutFooter,
- EuiFlyout,
- EuiTitle,
- EuiInMemoryTable,
- EuiSpacer,
- EuiButtonEmpty,
- EuiCallOut,
- EuiPortal,
-} from '@elastic/eui';
-
-export class NodeAttrsDetails extends PureComponent {
- static propTypes = {
- fetchNodeDetails: PropTypes.func.isRequired,
- close: PropTypes.func.isRequired,
-
- details: PropTypes.array,
- selectedNodeAttrs: PropTypes.string.isRequired,
- allocationRules: PropTypes.object,
- };
-
- componentWillMount() {
- this.props.fetchNodeDetails(this.props.selectedNodeAttrs);
- }
-
- render() {
- const { selectedNodeAttrs, allocationRules, details, close } = this.props;
-
- return (
-
-
-
-
- Nodes that contain the attribute: `{selectedNodeAttrs}`
-
-
- {allocationRules ? (
-
-
- Be aware that this index template has existing allocation rules
- which will affect the list of nodes these indices can be allocated to.
-
-
-
- ) : null}
-
-
-
-
- Close
-
-
-
-
- );
- }
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.container.js
deleted file mode 100644
index bfeb21f8d32f1..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.container.js
+++ /dev/null
@@ -1,34 +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 { connect } from 'react-redux';
-import { ColdPhase as PresentationComponent } from './cold_phase';
-import {
- getNodeOptions,
- getPhase,
- getPhaseData
-} from '../../../../../../store/selectors';
-import { setPhaseData, fetchNodes } from '../../../../../../store/actions';
-import {
- PHASE_COLD,
- PHASE_WARM,
- PHASE_REPLICA_COUNT
-} from '../../../../../../store/constants';
-
-export const ColdPhase = connect(
- state => ({
- phaseData: getPhase(state, PHASE_COLD),
- nodeOptions: getNodeOptions(state),
- warmPhaseReplicaCount: getPhaseData(state, PHASE_WARM, PHASE_REPLICA_COUNT)
- }),
- {
- setPhaseData: (key, value) => setPhaseData(PHASE_COLD, key, value),
- fetchNodes
- }
-)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.js
deleted file mode 100644
index 63c0da1a47f8a..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.js
+++ /dev/null
@@ -1,231 +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, { PureComponent, Fragment } from 'react';
-import PropTypes from 'prop-types';
-
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiSpacer,
- EuiText,
- EuiTextColor,
- EuiFormRow,
- EuiFieldNumber,
- EuiSelect,
- EuiButtonEmpty,
- EuiDescribedFormGroup,
- EuiBadge,
- EuiButton,
-} from '@elastic/eui';
-import {
- PHASE_ENABLED,
- PHASE_ROLLOVER_ALIAS,
- PHASE_ROLLOVER_MINIMUM_AGE,
- PHASE_ROLLOVER_MINIMUM_AGE_UNITS,
- PHASE_NODE_ATTRS,
- PHASE_REPLICA_COUNT
-} from '../../../../../../store/constants';
-import { ErrableFormRow } from '../../../../form_errors';
-
-export class ColdPhase extends PureComponent {
- static propTypes = {
- setPhaseData: PropTypes.func.isRequired,
- validate: PropTypes.func.isRequired,
- showNodeDetailsFlyout: PropTypes.func.isRequired,
-
- isShowingErrors: PropTypes.bool.isRequired,
- errors: PropTypes.object.isRequired,
- phaseData: PropTypes.shape({
- [PHASE_ENABLED]: PropTypes.bool.isRequired,
- [PHASE_ROLLOVER_ALIAS]: PropTypes.string.isRequired,
- [PHASE_ROLLOVER_MINIMUM_AGE]: PropTypes.oneOfType([
- PropTypes.number,
- PropTypes.string
- ]).isRequired,
- [PHASE_ROLLOVER_MINIMUM_AGE_UNITS]: PropTypes.string.isRequired,
- [PHASE_NODE_ATTRS]: PropTypes.string.isRequired,
- [PHASE_REPLICA_COUNT]: PropTypes.oneOfType([
- PropTypes.number,
- PropTypes.string
- ]).isRequired
- }).isRequired,
- warmPhaseReplicaCount: PropTypes.number.isRequired,
- nodeOptions: PropTypes.array.isRequired
- };
-
- componentWillMount() {
- this.props.fetchNodes();
- }
-
- render() {
- const {
- setPhaseData,
- validate,
- showNodeDetailsFlyout,
-
- phaseData,
- nodeOptions,
- warmPhaseReplicaCount,
- errors,
- isShowingErrors
- } = this.props;
-
- return (
-
- Cold phase{' '}
- {phaseData[PHASE_ENABLED] ? (
- Active
- ) : null}
-
- }
- titleSize="s"
- description={
-
-
- A cold index is queried less frequently
- and thus no longer needs to be on the most performant hardware.
-
- {isShowingErrors ? (
-
-
- This phase contains errors
-
-
- ) : null}
-
- }
- fullWidth
- >
- {phaseData[PHASE_ENABLED] ? (
-
-
-
-
- {
- await setPhaseData(PHASE_ENABLED, false);
- validate();
- }}
- >
- Deactive cold phase
-
-
-
-
-
-
-
- {
- setPhaseData(PHASE_ROLLOVER_MINIMUM_AGE, e.target.value);
- validate();
- }}
- min={1}
- />
-
-
-
-
-
- setPhaseData(PHASE_ROLLOVER_MINIMUM_AGE_UNITS, e.target.value)
- }
- options={[
- { value: 'd', text: 'days' },
- { value: 'h', text: 'hours' },
- ]}
- />
-
-
-
-
-
-
- showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])}
- >
- View a list of nodes attached to this configuration
-
- ) : null}
- >
- {
- await setPhaseData(PHASE_NODE_ATTRS, e.target.value);
- validate();
- }}
- />
-
-
-
-
-
- {
- await setPhaseData(PHASE_REPLICA_COUNT, e.target.value);
- validate();
- }}
- min={0}
- />
-
-
-
-
-
- setPhaseData(PHASE_REPLICA_COUNT, warmPhaseReplicaCount)
- }
- >
- Set to same as warm phase
-
-
-
-
-
- ) : (
-
-
- {
- await setPhaseData(PHASE_ENABLED, true);
- validate();
- }}
- >
- Activate cold phase
-
-
- )}
-
- );
- }
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/index.js
deleted file mode 100644
index e0d70ceb57726..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/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 { ColdPhase } from './cold_phase.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.container.js
deleted file mode 100644
index 661489d2d9aa9..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.container.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 { connect } from 'react-redux';
-import { DeletePhase as PresentationComponent } from './delete_phase';
-import { getPhase } from '../../../../../../store/selectors';
-import { setPhaseData } from '../../../../../../store/actions';
-import { PHASE_DELETE } from '../../../../../../store/constants';
-
-export const DeletePhase = connect(
- state => ({
- phaseData: getPhase(state, PHASE_DELETE)
- }),
- {
- setPhaseData: (key, value) => setPhaseData(PHASE_DELETE, key, value)
- }
-)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.js
deleted file mode 100644
index ab5258cc1a67e..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.js
+++ /dev/null
@@ -1,158 +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, { PureComponent, Fragment } from 'react';
-import PropTypes from 'prop-types';
-
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiTitle,
- EuiSpacer,
- EuiText,
- EuiTextColor,
- EuiFormRow,
- EuiFieldNumber,
- EuiSelect,
- EuiDescribedFormGroup,
- EuiBadge,
- EuiButton,
-} from '@elastic/eui';
-import {
- PHASE_ENABLED,
- PHASE_ROLLOVER_MINIMUM_AGE,
- PHASE_ROLLOVER_MINIMUM_AGE_UNITS,
-} from '../../../../../../store/constants';
-import { ErrableFormRow } from '../../../../form_errors';
-
-export class DeletePhase extends PureComponent {
- static propTypes = {
- setPhaseData: PropTypes.func.isRequired,
- validate: PropTypes.func.isRequired,
-
- isShowingErrors: PropTypes.bool.isRequired,
- errors: PropTypes.object.isRequired,
- phaseData: PropTypes.shape({
- [PHASE_ENABLED]: PropTypes.bool.isRequired,
- [PHASE_ROLLOVER_MINIMUM_AGE]: PropTypes.oneOfType([
- PropTypes.number,
- PropTypes.string
- ]).isRequired,
- [PHASE_ROLLOVER_MINIMUM_AGE_UNITS]: PropTypes.string.isRequired
- }).isRequired
- };
-
- render() {
- const {
- setPhaseData,
- validate,
- phaseData,
- errors,
- isShowingErrors
- } = this.props;
-
- return (
-
- Delete phase{' '}
- {phaseData[PHASE_ENABLED] ? (
- Active
- ) : null}
-
- }
- titleSize="s"
- description={
-
-
- Use this phase to define how long to retain your data.
-
- {isShowingErrors ? (
-
-
- This phase contains errors
-
-
- ) : null}
-
- }
- fullWidth
- >
- {phaseData[PHASE_ENABLED] ? (
-
-
-
-
- {
- await setPhaseData(PHASE_ENABLED, false);
- validate();
- }}
- >
- Deactive delete phase
-
-
-
-
-
- Configuration
-
-
-
-
-
- {
- setPhaseData(PHASE_ROLLOVER_MINIMUM_AGE, e.target.value);
- validate();
- }}
- min={1}
- />
-
-
-
-
-
- setPhaseData(PHASE_ROLLOVER_MINIMUM_AGE_UNITS, e.target.value)
- }
- options={[
- { value: 'd', text: 'days' },
- { value: 'h', text: 'hours' },
- ]}
- />
-
-
-
-
- ) : (
-
-
- {
- await setPhaseData(PHASE_ENABLED, true);
- validate();
- }}
- >
- Activate delete phase
-
-
- )}
-
- );
- }
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/index.js
deleted file mode 100644
index 5f909ab2c0f79..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/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 { DeletePhase } from './delete_phase.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.container.js
deleted file mode 100644
index 1db810b49c19c..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.container.js
+++ /dev/null
@@ -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 { connect } from 'react-redux';
-import { HotPhase as PresentationComponent } from './hot_phase';
-import { getPhase } from '../../../../../../store/selectors';
-import { setPhaseData } from '../../../../../../store/actions';
-import { PHASE_HOT } from '../../../../../../store/constants';
-
-export const HotPhase = connect(
- state => ({
- phaseData: getPhase(state, PHASE_HOT)
- }),
- {
- setPhaseData: (key, value) => setPhaseData(PHASE_HOT, key, value)
- },
-)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.js
deleted file mode 100644
index 347b0f1d8117f..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/hot_phase.js
+++ /dev/null
@@ -1,210 +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, { Fragment, PureComponent } from 'react';
-import PropTypes from 'prop-types';
-
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiSpacer,
- EuiText,
- EuiTextColor,
- EuiFieldNumber,
- EuiSelect,
- EuiSwitch,
- EuiFormRow,
- EuiDescribedFormGroup,
- EuiBadge,
-} from '@elastic/eui';
-import { LearnMoreLink } from '../../../../../../components/learn_more_link';
-import {
- PHASE_ROLLOVER_ALIAS,
- PHASE_ROLLOVER_MAX_AGE,
- PHASE_ROLLOVER_MAX_AGE_UNITS,
- PHASE_ROLLOVER_MAX_SIZE_STORED,
- PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS,
- PHASE_ROLLOVER_ENABLED,
- MAX_SIZE_TYPE_DOCUMENT
-} from '../../../../../../store/constants';
-
-import { ErrableFormRow } from '../../../../form_errors';
-
-export class HotPhase extends PureComponent {
- static propTypes = {
- setPhaseData: PropTypes.func.isRequired,
- validate: PropTypes.func.isRequired,
-
- isShowingErrors: PropTypes.bool.isRequired,
- errors: PropTypes.object.isRequired,
- phaseData: PropTypes.shape({
- [PHASE_ROLLOVER_ALIAS]: PropTypes.string.isRequired,
- [PHASE_ROLLOVER_MAX_AGE]: PropTypes.oneOfType([
- PropTypes.number,
- PropTypes.string
- ]).isRequired,
- [PHASE_ROLLOVER_MAX_AGE_UNITS]: PropTypes.string.isRequired,
- [PHASE_ROLLOVER_MAX_SIZE_STORED]: PropTypes.oneOfType([
- PropTypes.number,
- PropTypes.string
- ]).isRequired,
- [PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS]: PropTypes.string.isRequired
- }).isRequired
- };
-
- render() {
- const {
- validate,
- setPhaseData,
-
- phaseData,
- isShowingErrors,
- errors,
- } = this.props;
-
- return (
-
- Hot phase{' '}
- Active
-
- }
- titleSize="s"
- description={
-
-
- This phase is required. A hot index is being queried and actively written to.
- You can optimize this phase for write throughput.
-
- {isShowingErrors ? (
-
-
- This phase contains errors
-
-
- ) : null}
-
- }
- fullWidth
- >
-
- If true, rollover the index when it gets too big or too old. The alias switches to the new index.{' '}
-
-
- }
- >
- {
- await setPhaseData(PHASE_ROLLOVER_ENABLED, e.target.checked);
- validate();
- }}
- label="Enable rollover"
- />
-
- {phaseData[PHASE_ROLLOVER_ENABLED] ? (
-
-
-
-
-
- {
- await setPhaseData(
- PHASE_ROLLOVER_MAX_SIZE_STORED,
- e.target.value
- );
- validate();
- }}
- min={1}
- />
-
-
-
-
- {
- await setPhaseData(
- PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS,
- e.target.value
- );
- validate();
- }}
- options={[
- { value: 'gb', text: 'gigabytes' },
- { value: MAX_SIZE_TYPE_DOCUMENT, text: 'documents' }
- ]}
- />
-
-
-
-
-
-
-
- {
- await setPhaseData(PHASE_ROLLOVER_MAX_AGE, e.target.value);
- validate();
- }}
- min={1}
- />
-
-
-
-
- {
- await setPhaseData(
- PHASE_ROLLOVER_MAX_AGE_UNITS,
- e.target.value
- );
- validate();
- }}
- options={[
- { value: 'd', text: 'days' },
- { value: 'h', text: 'hours' },
- ]}
- />
-
-
-
-
- ) : null}
-
- );
- }
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/index.js
deleted file mode 100644
index 114e34c3ef4d0..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/hot_phase/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 { HotPhase } from './hot_phase.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/index.js
deleted file mode 100644
index 7eb5def486c87..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/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 { WarmPhase } from './warm_phase.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.container.js
deleted file mode 100644
index 95176ef3498ca..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.container.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 { connect } from 'react-redux';
-import { WarmPhase as PresentationComponent } from './warm_phase';
-import {
- getNodeOptions,
- getPhase,
- getSelectedReplicaCount,
- getSelectedPrimaryShardCount
-} from '../../../../../../store/selectors';
-import { setPhaseData, fetchNodes } from '../../../../../../store/actions';
-import { PHASE_WARM, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../../../store/constants';
-
-export const WarmPhase = connect(
- state => ({
- phaseData: getPhase(state, PHASE_WARM),
- hotPhaseReplicaCount: Number(getSelectedReplicaCount(state)),
- hotPhasePrimaryShardCount: Number(getSelectedPrimaryShardCount(state)),
- hotPhaseRolloverEnabled: getPhase(state, PHASE_HOT)[PHASE_ROLLOVER_ENABLED],
- nodeOptions: getNodeOptions(state)
- }),
- {
- setPhaseData: (key, value) => setPhaseData(PHASE_WARM, key, value),
- fetchNodes
- }
-)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.js
deleted file mode 100644
index 8685f0b86a22a..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.js
+++ /dev/null
@@ -1,371 +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, { Fragment, PureComponent } from 'react';
-import PropTypes from 'prop-types';
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiTitle,
- EuiSpacer,
- EuiText,
- EuiTextColor,
- EuiFormRow,
- EuiFieldNumber,
- EuiSelect,
- EuiSwitch,
- EuiButtonEmpty,
- EuiDescribedFormGroup,
- EuiBadge,
- EuiButton,
-} from '@elastic/eui';
-import {
- PHASE_ENABLED,
- WARM_PHASE_ON_ROLLOVER,
- PHASE_ROLLOVER_ALIAS,
- PHASE_FORCE_MERGE_ENABLED,
- PHASE_FORCE_MERGE_SEGMENTS,
- PHASE_NODE_ATTRS,
- PHASE_PRIMARY_SHARD_COUNT,
- PHASE_REPLICA_COUNT,
- PHASE_ROLLOVER_MINIMUM_AGE,
- PHASE_ROLLOVER_MINIMUM_AGE_UNITS,
- PHASE_SHRINK_ENABLED,
-} from '../../../../../../store/constants';
-import { ErrableFormRow } from '../../../../form_errors';
-import { LearnMoreLink } from '../../../../../../components/learn_more_link';
-
-export class WarmPhase extends PureComponent {
- static propTypes = {
- setPhaseData: PropTypes.func.isRequired,
- validate: PropTypes.func.isRequired,
- showNodeDetailsFlyout: PropTypes.func.isRequired,
-
- isShowingErrors: PropTypes.bool.isRequired,
- errors: PropTypes.object.isRequired,
- phaseData: PropTypes.shape({
- [PHASE_ENABLED]: PropTypes.bool.isRequired,
- [WARM_PHASE_ON_ROLLOVER]: PropTypes.bool.isRequired,
- [PHASE_ROLLOVER_ALIAS]: PropTypes.string.isRequired,
- [PHASE_FORCE_MERGE_ENABLED]: PropTypes.bool.isRequired,
- [PHASE_FORCE_MERGE_SEGMENTS]: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
- .isRequired,
- [PHASE_NODE_ATTRS]: PropTypes.string.isRequired,
- [PHASE_PRIMARY_SHARD_COUNT]: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
- .isRequired,
- [PHASE_REPLICA_COUNT]: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
- [PHASE_ROLLOVER_MINIMUM_AGE]: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
- [PHASE_ROLLOVER_MINIMUM_AGE_UNITS]: PropTypes.string.isRequired,
- }).isRequired,
-
- hotPhaseReplicaCount: PropTypes.number.isRequired,
- hotPhasePrimaryShardCount: PropTypes.number.isRequired,
-
- nodeOptions: PropTypes.array.isRequired,
- };
-
- componentWillMount() {
- this.props.fetchNodes();
- }
-
- render() {
- const {
- validate,
- setPhaseData,
- showNodeDetailsFlyout,
-
- phaseData,
- hotPhaseReplicaCount,
- hotPhasePrimaryShardCount,
- nodeOptions,
- errors,
- isShowingErrors,
- hotPhaseRolloverEnabled,
- } = this.props;
-
- return (
-
- Warm phase{' '}
- {phaseData[PHASE_ENABLED] ? (
- Active
- ) : null}
-
- }
- titleSize="s"
- description={
-
-
- Your index becomes read-only when it enters the warm phase. You can optimize this
- phase for search.
-
- {isShowingErrors ? (
-
-
- This phase contains errors
-
-
- ) : null}
-
- }
- fullWidth
- >
-
- {phaseData[PHASE_ENABLED] ? (
-
-
-
- {
- await setPhaseData(PHASE_ENABLED, false);
- validate();
- }}
- >
- Deactivate warm phase
-
-
-
- {hotPhaseRolloverEnabled ? (
-
- {
- await setPhaseData(WARM_PHASE_ON_ROLLOVER, e.target.checked);
- validate();
- }}
- />
-
- ) : null}
- {!phaseData[WARM_PHASE_ON_ROLLOVER] ? (
-
-
-
- {
- setPhaseData(PHASE_ROLLOVER_MINIMUM_AGE, e.target.value);
- validate();
- }}
- min={1}
- />
-
-
-
-
- {
- await setPhaseData(PHASE_ROLLOVER_MINIMUM_AGE_UNITS, e.target.value);
- validate();
- }}
- options={[
- { value: 'd', text: 'days' },
- { value: 'h', text: 'hours' },
- ]}
- />
-
-
-
- ) : null}
-
-
-
- showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])}
- >
- View node details
-
- ) : null
- }
- >
- {
- await setPhaseData(PHASE_NODE_ATTRS, e.target.value);
- validate();
- }}
- />
-
-
-
-
-
- {
- await setPhaseData(PHASE_REPLICA_COUNT, e.target.value);
- validate();
- }}
- min={0}
- />
-
-
-
-
- {
- await setPhaseData(PHASE_REPLICA_COUNT, hotPhaseReplicaCount);
- validate();
- }}
- >
- Set to same as hot phase
-
-
-
-
-
- {hotPhasePrimaryShardCount > 1 ? (
-
-
-
- Shrink
-
-
-
- Shrink the index into a new index with fewer primary shards.{' '}
-
-
-
-
-
-
- {
- await setPhaseData(PHASE_SHRINK_ENABLED, e.target.checked);
- validate();
- }}
- label="Shrink index"
- />
- {phaseData[PHASE_SHRINK_ENABLED] ? (
-
-
-
-
- {
- await setPhaseData(PHASE_PRIMARY_SHARD_COUNT, e.target.value);
- validate();
- }}
- min={1}
- />
-
-
-
-
- {
- await setPhaseData(
- PHASE_PRIMARY_SHARD_COUNT,
- hotPhasePrimaryShardCount
- );
- validate();
- }}
- >
- Set to same as hot phase
-
-
-
-
-
-
-
- ) : null}
-
- ) : null}
-
-
-
-
- Force merge
-
-
-
- Reduce the number of segments in your shard by merging smaller files and clearing
- deleted ones.
-
-
-
-
-
- {
- await setPhaseData(PHASE_FORCE_MERGE_ENABLED, e.target.checked);
- validate();
- }}
- />
-
-
-
- {phaseData[PHASE_FORCE_MERGE_ENABLED] ? (
-
- {
- await setPhaseData(PHASE_FORCE_MERGE_SEGMENTS, e.target.value);
- validate();
- }}
- min={1}
- />
-
- ) : null}
-
- ) : (
-
-
- {
- await setPhaseData(PHASE_ENABLED, true);
- validate();
- }}
- >
- Activate warm phase
-
-
-
- )}
-
-
- );
- }
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/index.js
deleted file mode 100644
index d8a885b0b32f3..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/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 { PolicyConfiguration } from './policy_configuration.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.container.js
deleted file mode 100644
index 233e39776265a..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.container.js
+++ /dev/null
@@ -1,47 +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 { connect } from 'react-redux';
-import { PolicyConfiguration as PresentationComponent } from './policy_configuration';
-import {
- getSelectedPolicyName,
- getAffectedIndexTemplates,
- getSelectedIndexTemplateName,
- getBootstrapEnabled,
- getIndexName,
- getAliasName,
- getSelectedOriginalPolicyName,
- getIsSelectedPolicySet,
- getPolicies
-} from '../../../../store/selectors';
-import {
- setBootstrapEnabled,
- setIndexName,
- setAliasName,
- setSelectedPolicyName,
- unsetSelectedPolicy
-} from '../../../../store/actions';
-
-export const PolicyConfiguration = connect(
- state => ({
- isSelectedPolicySet: getIsSelectedPolicySet(state),
- selectedPolicyName: getSelectedPolicyName(state),
- selectedIndexTemplateName: getSelectedIndexTemplateName(state),
- affectedIndexTemplates: getAffectedIndexTemplates(state),
- bootstrapEnabled: getBootstrapEnabled(state),
- indexName: getIndexName(state),
- aliasName: getAliasName(state),
- originalPolicyName: getSelectedOriginalPolicyName(state),
- hasExistingPolicies: getPolicies(state).length > 0
- }),
- {
- setBootstrapEnabled,
- setIndexName,
- setAliasName,
- setSelectedPolicyName,
- unsetSelectedPolicy
- }
-)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.js
deleted file mode 100644
index df406b14c76d0..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.js
+++ /dev/null
@@ -1,177 +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, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { toastNotifications } from 'ui/notify';
-
-import {
- EuiTitle,
- EuiText,
- EuiSpacer,
- EuiHorizontalRule,
- EuiButton,
- EuiButtonEmpty,
- EuiFlexGroup,
- EuiFlexItem,
-} from '@elastic/eui';
-import { HotPhase } from './components/hot_phase';
-import { WarmPhase } from './components/warm_phase';
-import { DeletePhase } from './components/delete_phase';
-import { ColdPhase } from './components/cold_phase';
-import {
- PHASE_HOT,
- PHASE_COLD,
- PHASE_DELETE,
- PHASE_WARM,
-} from '../../../../store/constants';
-import { hasErrors } from '../../../../lib/find_errors';
-import { NodeAttrsDetails } from '../node_attrs_details';
-import { PolicySelection } from '../policy_selection/policy_selection.container';
-
-export class PolicyConfiguration extends Component {
- static propTypes = {
- setSelectedPolicyName: PropTypes.func.isRequired,
- setIndexName: PropTypes.func.isRequired,
- setAliasName: PropTypes.func.isRequired,
- setBootstrapEnabled: PropTypes.func.isRequired,
- done: PropTypes.func.isRequired,
- back: PropTypes.func.isRequired,
- validate: PropTypes.func.isRequired,
- selectedPolicyName: PropTypes.string.isRequired,
- errors: PropTypes.object.isRequired,
- bootstrapEnabled: PropTypes.bool.isRequired,
- indexName: PropTypes.string.isRequired,
- aliasName: PropTypes.string.isRequired,
- originalPolicyName: PropTypes.string,
- };
-
- constructor(props) {
- super(props);
- this.state = {
- isShowingErrors: false,
- isShowingNodeDetailsFlyout: false,
- selectedNodeAttrsForDetails: undefined,
- };
- }
-
- validate = async () => {
- await this.props.validate();
- const noErrors = !hasErrors(this.props.errors);
- return noErrors;
- };
- componentDidMount() {
- window.scrollTo(0, 0);
- }
- submit = async () => {
- this.setState({ isShowingErrors: true });
- if (await this.validate()) {
- this.props.done();
- } else {
- toastNotifications.addDanger('Please the fix errors on the page');
- }
- };
-
- showNodeDetailsFlyout = selectedNodeAttrsForDetails => {
- this.setState({ isShowingNodeDetailsFlyout: true, selectedNodeAttrsForDetails });
- }
-
- render() {
- const {
- back,
-
- selectedPolicyName,
- isSelectedPolicySet,
- errors,
- unsetSelectedPolicy,
- hasExistingPolicies
- } = this.props;
-
- const { isShowingErrors } = this.state;
-
- if (!isSelectedPolicySet) {
- return (
-
- );
- }
-
- return (
-
-
-
-
-
-
-
- {!selectedPolicyName ? 'Create a lifecycle policy' : `Edit lifecycle policy ${selectedPolicyName}`}
-
-
-
- {hasExistingPolicies ? (
-
- Change lifecycle policy
-
- ) : null}
-
-
-
- Configure the phases of your data and when to transition between them.
-
-
-
-
-
-
-
-
-
-
-
-
- Back
-
-
-
- Continue
-
-
- {this.state.isShowingNodeDetailsFlyout ? (
-
this.setState({ isShowingNodeDetailsFlyout: false })}
- />
- ) : null}
-
- );
- }
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/index.js
deleted file mode 100644
index 447bc384c368d..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/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 { PolicySelection } from './policy_selection.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.container.js
deleted file mode 100644
index 59ce80fc1f0a4..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.container.js
+++ /dev/null
@@ -1,30 +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 { connect } from 'react-redux';
-import { PolicySelection as PresentationComponent } from './policy_selection';
-import {
- getPolicies, getIsSelectedPolicySet, getSelectedPolicyName,
-} from '../../../../store/selectors';
-import {
- fetchPolicies,
- setSelectedPolicy,
-} from '../../../../store/actions';
-
-export const PolicySelection = connect(
- state => ({
- isSelectedPolicySet: getIsSelectedPolicySet(state),
- policies: getPolicies(state),
- selectedPolicyName: getSelectedPolicyName(state),
- }),
- {
- fetchPolicies,
- setSelectedPolicy,
- }
-)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.js
deleted file mode 100644
index e153d9fd1ce03..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_selection/policy_selection.js
+++ /dev/null
@@ -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 React, { Component } from 'react';
-import PropTypes from 'prop-types';
-
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiButton,
- EuiDescribedFormGroup,
- EuiFormRow,
- EuiSelect,
-} from '@elastic/eui';
-
-export class PolicySelection extends Component {
- static propTypes = {
- fetchPolicies: PropTypes.func.isRequired,
- setSelectedPolicy: PropTypes.func.isRequired,
-
- selectedPolicyName: PropTypes.string.isRequired,
- policies: PropTypes.array.isRequired,
- };
-
- componentDidMount() {
- this.props.fetchPolicies();
- }
- selectPolicy(policyName) {
- const policy = this.props.policies.find(policy => policy.name === policyName);
- this.props.setSelectedPolicy(policy);
- }
-
- render() {
- const { isSelectedPolicySet, policies, selectedPolicyName } = this.props;
- const policiesExist = policies.length > 0;
- if (isSelectedPolicySet) {
- return null;
- }
- let existingPoliciesSelect;
- if (policiesExist) {
- const options = policies.map(item => ({ value: item.name, text: item.name }));
- options.unshift({ value: '', text: 'Select an existing policy' });
- existingPoliciesSelect = (
-
-
- {
- await this.selectPolicy(e.target.value);
- }}
- />
-
-
- );
- }
-
- return (
- Select or create a lifecycle policy}
- titleSize="s"
- description={`An index lifecycle policy is a
- blueprint for transitioning your data over time.
- You can create a new policy${policiesExist ? ' or edit an existing policy and save it with a new name.' : '.'}`}
- fullWidth
- >
-
-
- {existingPoliciesSelect}
-
- - OR -
-
-
- this.selectPolicy()}>Create lifecycle policy
-
-
-
-
- );
- }
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/diff_view.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/diff_view.js
deleted file mode 100644
index a89f7e2412c59..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/diff_view.js
+++ /dev/null
@@ -1,107 +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, { PureComponent } from 'react';
-import PropTypes from 'prop-types';
-
-import {
- EuiCodeEditor,
- EuiFlexGroup,
- EuiFlexItem,
- EuiButtonEmpty,
- EuiToolTip,
- EuiCode,
-} from '@elastic/eui';
-import ace from 'brace';
-import 'brace/mode/json';
-import {
- mergeAndPreserveDuplicateKeys,
- removePrefixes,
-} from '../../../../lib/diff_tools';
-import { addDiffAddonsForAce, setCurrentJsonObject } from '../../../../lib/diff_ace_addons';
-
-export class DiffView extends PureComponent {
- static propTypes = {
- templateDiff: PropTypes.shape({
- originalFullIndexTemplate: PropTypes.object.isRequired,
- newFullIndexTemplate: PropTypes.object.isRequired,
- }).isRequired,
- };
-
- scrollToKey = (key, value) => {
- const editorDom = this.aceEditor.aceEditor.refEditor;
- const editor = ace.edit(editorDom);
- const escapedValue = value.replace(/\^/g, '\\^');
- const range = editor.find(new RegExp(`"${key}"\\s*:\\s*"*(${escapedValue})"*`), { regex: true });
- if (!range) {
- return;
- }
- editor.gotoLine(range.start.row + 1, range.start.column);
- }
-
- render() {
- const {
- templateDiff: { originalFullIndexTemplate, newFullIndexTemplate },
- } = this.props;
-
- const { result: mergedJson, changes } = mergeAndPreserveDuplicateKeys(
- originalFullIndexTemplate,
- newFullIndexTemplate
- );
-
- // Strip the ^ and $ characters
- const mergedJsonAsString = removePrefixes(
- JSON.stringify(mergedJson, null, 2)
- );
-
- setCurrentJsonObject(mergedJson);
- addDiffAddonsForAce();
-
- return (
-
-
-
- {changes.map(({ key, original, updated }) => (
- -
-
- Changing the value of {key} from {JSON.stringify(original)}
- to {JSON.stringify(updated)}
-
- ) : (
- Setting a value of {JSON.stringify(updated)} for {key}
- )}
- >
- this.scrollToKey(key, updated)}>
- {key}
-
-
-
- ))}
-
-
-
- (this.aceEditor = aceEditor)}
- mode="diff_json"
- theme="github"
- width="100%"
- value={mergedJsonAsString}
- setOptions={{
- useWorker: false,
- readOnly: true,
- }}
- editorProps={{
- $blockScrolling: Infinity,
- }}
- />
-
-
- );
- }
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/index.js
deleted file mode 100644
index defebab0131ea..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/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 { Review } from './review.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.container.js
deleted file mode 100644
index 044648dbbcabd..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.container.js
+++ /dev/null
@@ -1,59 +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 { connect } from 'react-redux';
-import { Review as PresentationComponent } from './review';
-import {
- getSelectedIndexTemplateName,
- getAffectedIndexTemplates,
- getTemplateDiff,
- getLifecycle,
- getSelectedPolicyName,
- getSaveAsNewPolicy,
- getSelectedOriginalPolicyName,
- getAliasName,
- getBootstrapEnabled,
- getIndexName,
- getPolicies,
- getIsNewPolicy
-} from '../../../../store/selectors';
-import {
- setSelectedPolicyName,
- setSaveAsNewPolicy,
- setAliasName,
- setIndexName,
- setBootstrapEnabled,
-} from '../../../../store/actions';
-
-export const Review = connect(
- state => ({
- selectedIndexTemplateName: getSelectedIndexTemplateName(state),
- affectedIndexTemplates: getAffectedIndexTemplates(state),
- policies: getPolicies(state),
- templateDiff: getTemplateDiff(state),
- lifecycle: getLifecycle(state),
- bootstrapEnabled: getBootstrapEnabled(state),
- aliasName: getAliasName(state),
- selectedPolicyName: getSelectedPolicyName(state),
- saveAsNewPolicy: getSaveAsNewPolicy(state),
- originalPolicyName: getSelectedOriginalPolicyName(state),
- isNewPolicy: getIsNewPolicy(state),
-
- /* start might go away */
- indexName: getIndexName(state),
- /* end might go away */
- }),
- {
- setSelectedPolicyName,
- setSaveAsNewPolicy,
- setBootstrapEnabled,
- setIndexName,
- setAliasName,
- }
-)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.js
deleted file mode 100644
index 20302c08de61f..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.js
+++ /dev/null
@@ -1,286 +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, { Fragment, Component } from 'react';
-import PropTypes from 'prop-types';
-import { toastNotifications } from 'ui/notify';
-
-import './review.less';
-
-import 'brace/theme/github';
-import 'brace/mode/json';
-import 'brace/snippets/json';
-import 'brace/ext/language_tools';
-
-import {
- EuiTitle,
- EuiCode,
- EuiCallOut,
- EuiSpacer,
- EuiHorizontalRule,
- EuiButton,
- EuiFlexItem,
- EuiText,
- EuiButtonEmpty,
- EuiFormRow,
- EuiSwitch,
- EuiFieldText,
- EuiLoadingSpinner,
- EuiFlexGroup,
-} from '@elastic/eui';
-import { getAffectedIndices } from '../../../../api';
-import { DiffView } from './diff_view';
-import { ErrableFormRow } from '../../form_errors';
-import { STRUCTURE_POLICY_NAME } from '../../../../store/constants';
-import { hasErrors } from '../../../../lib/find_errors';
-
-export class Review extends Component {
- static propTypes = {
- setSelectedPolicyName: PropTypes.func.isRequired,
- setSaveAsNewPolicy: PropTypes.func.isRequired,
- done: PropTypes.func.isRequired,
- back: PropTypes.func.isRequired,
-
- selectedIndexTemplateName: PropTypes.string.isRequired,
- affectedIndexTemplates: PropTypes.array.isRequired,
- templateDiff: PropTypes.object.isRequired,
- lifecycle: PropTypes.object.isRequired,
- selectedPolicyName: PropTypes.string.isRequired,
- saveAsNewPolicy: PropTypes.bool.isRequired,
- originalPolicyName: PropTypes.string,
- bootstrapEnabled: PropTypes.bool.isRequired,
- aliasName: PropTypes.string.isRequired,
- };
-
- constructor(props) {
- super(props);
- this.state = {
- selectedTab: 1,
- affectedIndices: [],
- isLoadingAffectedIndices: false,
- };
-
- this.currentFetchTimeout = null;
- }
- componentDidMount() {
- window.scrollTo(0, 0);
- }
- fetchAffectedIndices = () => {
- if (this.currentFetchTimeout) {
- clearTimeout(this.currentFetchTimeout);
- }
-
- this.setState({ isLoadingAffectedIndices: true });
- this.currentFetchTimeout = setTimeout(async () => {
- const affectedIndices = await getAffectedIndices(
- this.props.selectedIndexTemplateName,
- this.props.selectedPolicyName
- );
- this.setState({ affectedIndices, isLoadingAffectedIndices: false });
- }, 1000);
- }
-
- async componentWillMount() {
- this.fetchAffectedIndices();
- }
-
- async componentWillReceiveProps(nextProps) {
- if (nextProps.selectedPolicyName !== this.props.selectedPolicyName) {
- this.fetchAffectedIndices();
- }
- }
-
- validate = async () => {
- await this.props.validate();
- const noErrors = !hasErrors(this.props.errors);
- return noErrors;
- };
-
- submit = async () => {
- this.setState({ isShowingErrors: true });
- if (await this.validate()) {
- this.props.done();
- } else {
- toastNotifications.addDanger('Please fix the errors on the page');
- }
- };
-
- render() {
- const {
- done,
- back,
- setSelectedPolicyName,
- setSaveAsNewPolicy,
- validate,
-
- errors,
- selectedPolicyName,
- saveAsNewPolicy,
- originalPolicyName,
- selectedIndexTemplateName,
- affectedIndexTemplates,
- templateDiff,
- lifecycle,
- bootstrapEnabled,
- aliasName,
- policies,
- isNewPolicy
- } = this.props;
-
- const { affectedIndices, isLoadingAffectedIndices, isShowingErrors } = this.state;
-
- const showSaveChangedMessage = (originalPolicyName && !saveAsNewPolicy)
- || (saveAsNewPolicy && !!policies.find(policy => policy.name === selectedPolicyName));
-
- return (
-
-
-
- Review your policy changes
-
-
- When you save a policy, your changes go into effect immediately.
-
-
-
-
-
- {`${affectedIndexTemplates.length} Index ${affectedIndexTemplates.length === 1 ? 'template' : 'templates'}`}
-
- {affectedIndexTemplates.map(template => (
- - {template}
- ))}
-
- {`${affectedIndices.length} ${affectedIndices.length === 1 ? 'Index' : 'Indices' }`}
- { isLoadingAffectedIndices ? (
-
- ) : (
-
- {affectedIndices.map(index => - {index}
)}
-
- ) }
-
-
- {bootstrapEnabled ? (
-
-
-
- You decided to bootstrap a new index. Point to this new alias going forward.
- {aliasName} is your new alias
-
-
- ) : null}
-
-
- {templateDiff.hasChanged ? (
-
-
-
- {selectedIndexTemplateName} index template changes
-
-
-
-
-
-
- ) : null}
-
-
-
- {originalPolicyName ? (
-
- { showSaveChangedMessage ? (
-
-
- Save changes to {selectedPolicyName} policy?
-
-
-
- You are editing an existing policy. Any changes you make
- will also change index templates that this policy is attached to. Alternately, you can save
- these changes in a new policy and only change the index template you
- selected.
-
-
-
-
- ) : null }
- { isNewPolicy ? null : (
-
- {
- await setSaveAsNewPolicy(e.target.checked);
- validate();
- }}
- label={
-
- Save this as a new policy
-
- }
- />
-
- )}
-
-
- ) : null}
- {saveAsNewPolicy || isNewPolicy ? (
-
-
- Save your work
-
-
-
- {
- await setSelectedPolicyName(e.target.value);
- validate();
- }}
- />
-
-
- ) : null}
-
-
-
-
-
- Back
-
-
-
-
- done(lifecycle)}
- disabled={!selectedPolicyName}
- >
- Looks good, save changes
-
-
-
-
-
- );
- }
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.less b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.less
deleted file mode 100644
index e826e78a7bf7e..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/review.less
+++ /dev/null
@@ -1,7 +0,0 @@
-.ace_diff_addition {
- background-color: #e6ffed;
-}
-
-.ace_diff_removal {
- background-color: #ffeef0;
-}
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/form_errors.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/form_errors.js
deleted file mode 100644
index fc3c29c4beb0c..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/form_errors.js
+++ /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 React, { cloneElement, Children, Fragment } from 'react';
-import { EuiFormRow } from '@elastic/eui';
-
-export const ErrableFormRow = ({
- errorKey,
- isShowingErrors,
- errors,
- children,
- ...rest
-}) => {
- return (
- 0
- }
- error={errors[errorKey]}
- {...rest}
- >
-
- {Children.map(children, child => cloneElement(child, {
- isInvalid: isShowingErrors && errors[errorKey].length > 0,
- }))}
-
-
- );
-};
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/index.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/index.js
deleted file mode 100644
index 3a6f61a7c0492..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/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 { Wizard } from './wizard.container';
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.container.js
deleted file mode 100644
index 84c94f2c82387..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.container.js
+++ /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 { connect } from 'react-redux';
-import '../../less/main.less';
-import { Wizard as PresentationComponent } from './wizard';
-import { saveLifecycle, fetchIndexTemplates } from '../../store/actions';
-
-import {
- getIndexTemplates,
- getIndexTemplatePatch,
- getBootstrapEnabled,
- getIndexName,
- getAliasName,
- validateLifecycle,
-} from '../../store/selectors';
-
-export const Wizard = connect(
- state => ({
- indexTemplatePatch: getIndexTemplatePatch(state),
- bootstrapEnabled: getBootstrapEnabled(state),
- indexName: getIndexName(state),
- aliasName: getAliasName(state),
- validateLifecycle: () => validateLifecycle(state),
- indexTemplates: getIndexTemplates(state),
- }),
- {
- fetchIndexTemplates,
- saveLifecycle
- }
-)(PresentationComponent);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js
deleted file mode 100644
index 8d98a13616b99..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js
+++ /dev/null
@@ -1,177 +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, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { toastNotifications } from 'ui/notify';
-import { IndexTemplate } from './components/index_template';
-import { PolicyConfiguration } from './components/policy_configuration';
-import { Review } from './components/review';
-import { goToPolicyList } from '../../services/navigation';
-import {
- EuiPage,
- EuiPageBody,
- EuiPageContent,
- EuiTitle,
- EuiSpacer,
- EuiStepsHorizontal,
-} from '@elastic/eui';
-import { bootstrap } from '../../api';
-import {
- STRUCTURE_INDEX_TEMPLATE,
- STRUCTURE_POLICY_CONFIGURATION,
- STRUCTURE_REVIEW,
-} from '../../store/constants';
-
-const STEP_INDEX_TEMPLATE = 1;
-const STEP_POLICY_CONFIGURATION = 2;
-const STEP_REVIEW = 3;
-export class Wizard extends Component {
- static propTypes = {
- saveLifecycle: PropTypes.func.isRequired,
- validateLifecycle: PropTypes.func.isRequired,
-
- indexTemplatePatch: PropTypes.object.isRequired,
- bootstrapEnabled: PropTypes.bool.isRequired,
- indexName: PropTypes.string.isRequired,
- aliasName: PropTypes.string.isRequired,
- fetchIndexTemplates: PropTypes.func.isRequired,
- indexTemplates: PropTypes.array,
- };
-
- constructor(props) {
- super(props);
-
- this.state = {
- selectedStep: STEP_INDEX_TEMPLATE,
- errors: this.getErrors(),
- };
- }
- componentDidMount() {
- this.props.fetchIndexTemplates();
- }
- onSelectedStepChanged = selectedStep => {
- this.setState({
- selectedStep,
- });
- };
-
- getErrors = () => {
- return this.props.validateLifecycle();
- };
-
- validate = () => {
- const errors = this.getErrors();
- this.setState({ errors });
- };
-
- addLifecycle = async lifecycle => {
- const lifecycleSuccess = await this.props.saveLifecycle(lifecycle, this.props.indexTemplatePatch);
- if (!lifecycleSuccess) {
- return;
- }
- const bootstrapSuccess = await this.bootstrap();
- if (bootstrapSuccess) {
- goToPolicyList();
- }
- };
-
- bootstrap = async () => {
- const { indexName, aliasName, bootstrapEnabled } = this.props;
- if (!bootstrapEnabled) {
- return true;
- }
-
- const bootstrapSuccess = await bootstrap(indexName, aliasName);
- if (bootstrapSuccess) {
- toastNotifications.addSuccess(
- 'Successfully bootstrapped an index and alias'
- );
- // Bounce back to management
- // this.onSelectedStepChanged(1);
- // TODO: also clear state?
- } else {
- toastNotifications.addDanger('Unable to bootstrap an index and alias');
- }
- return bootstrapSuccess;
- };
-
- renderContent() {
- const { selectedStep, errors } = this.state;
-
- switch (selectedStep) {
- case STEP_INDEX_TEMPLATE:
- return (
- this.onSelectedStepChanged(selectedStep + 1)}
- />
- );
- case STEP_POLICY_CONFIGURATION:
- return (
- this.onSelectedStepChanged(selectedStep + 1)}
- back={() => this.onSelectedStepChanged(selectedStep - 1)}
- />
- );
- case STEP_REVIEW:
- return (
- this.onSelectedStepChanged(selectedStep - 1)}
- />
- );
- }
- }
- createStep(title, stepIndex) {
- return {
- title,
- isSelected: this.state.selectedStep === stepIndex,
- isComplete: this.state.selectedStep > stepIndex,
- onClick: () => this.onSelectedStepChanged(stepIndex),
- };
- }
- render() {
- const { indexTemplates } = this.props;
- if (indexTemplates === null) {
- // Loading...
- return null;
- }
-
- if (indexTemplates.length === 0) {
- return (
- No index templates found.
- );
- }
- const steps = [
- this.createStep('Select an index template', STEP_INDEX_TEMPLATE),
- this.createStep('Configure a lifecycle policy', STEP_POLICY_CONFIGURATION),
- this.createStep('Review and save', STEP_REVIEW),
- ];
-
- return (
-
-
-
-
- Index lifecycle management
-
-
-
-
-
- {this.renderContent()}
-
-
-
- );
- }
-}
From 717bda897b299d808f3570bad1bd8cbd0114959b Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Thu, 25 Oct 2018 15:48:49 -0400
Subject: [PATCH 076/102] fixing issue with edit policy
---
.../sections/edit_policy/edit_policy.container.js | 2 ++
.../public/sections/edit_policy/edit_policy.js | 7 ++++---
.../public/store/selectors/lifecycle.js | 13 +++++++------
3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.container.js
index 2f3ab4a14b37a..a57280ed62dba 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.container.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.container.js
@@ -14,6 +14,7 @@ import {
getLifecycle,
getPolicies,
isPolicyListLoaded,
+ getIsNewPolicy
} from '../../store/selectors';
import {
setSelectedPolicy,
@@ -32,6 +33,7 @@ export const EditPolicy = connect(
lifecycle: getLifecycle(state),
policies: getPolicies(state),
isPolicyListLoaded: isPolicyListLoaded(state),
+ isNewPolicy: getIsNewPolicy(state),
}),
{
setSelectedPolicy,
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
index 5cf7026f7bd55..4686efb39928d 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
@@ -115,6 +115,7 @@ export class EditPolicy extends Component {
setSaveAsNewPolicy,
saveAsNewPolicy,
setSelectedPolicyName,
+ isNewPolicy,
} = this.props;
const selectedPolicyName = selectedPolicy.name;
const { isShowingErrors } = this.state;
@@ -129,9 +130,9 @@ export class EditPolicy extends Component {
>
- {!selectedPolicyName
- ? 'Create a lifecycle policy'
- : `Edit lifecycle policy ${selectedPolicyName}`}
+ {isNewPolicy
+ ? 'Create an index lifecycle policy'
+ : `Edit index lifecycle policy ${selectedPolicyName}`}
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
index cfd3d389a5628..a6c24a2d90596 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
@@ -30,6 +30,7 @@ import {
getSelectedPrimaryShardCount,
getSaveAsNewPolicy,
getSelectedOriginalPolicyName,
+ getPolicies
} from '.';
export const validatePhase = (type, phase, errors) => {
@@ -106,12 +107,12 @@ export const validateLifecycle = state => {
errors[STRUCTURE_POLICY_NAME].push('The policy name must be different');
}
- // if (getSaveAsNewPolicy(state)) {
- // const policyNames = getAllPolicyNamesFromTemplates(state);
- // if (policyNames.includes(getSelectedPolicyName(state))) {
- // errors[STRUCTURE_POLICY_NAME].push('That policy name is already used.');
- // }
- // }
+ if (getSaveAsNewPolicy(state)) {
+ const policyNames = getPolicies(state).map(policy => policy.name);
+ if (policyNames.includes(getSelectedPolicyName(state))) {
+ errors[STRUCTURE_POLICY_NAME].push('That policy name is already used.');
+ }
+ }
const hotPhase = getPhase(state, PHASE_HOT);
const warmPhase = getPhase(state, PHASE_WARM);
From b34c2bd327fb25dec726de152b53512aed310f83 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Fri, 26 Oct 2018 09:41:56 -0400
Subject: [PATCH 077/102] fixing issue with closing delete confirmation modal
---
.../policy_table/components/policy_table/confirm_delete.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/confirm_delete.js b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/confirm_delete.js
index 9b3e250d6f958..d3ad96e8b1b8c 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/confirm_delete.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/confirm_delete.js
@@ -35,7 +35,7 @@ export class ConfirmDelete extends Component {
cancelButtonText="Cancel"
confirmButtonText="Delete"
buttonColor="danger"
- onClose={() => {}}
+ onClose={onCancel}
>
This operation cannot be undone.
From 257401b61ef1ce5b3720066199505a87bf8a3c24 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Tue, 30 Oct 2018 08:17:12 -0400
Subject: [PATCH 078/102] making max age and max size not mutually exclusive
---
.../public/store/selectors/policies.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
index 9cf603c071faf..6f87e542dd9f1 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
@@ -236,7 +236,8 @@ export const phaseToES = (state, phase) => {
esPhase.actions.rollover.max_age = `${phase[PHASE_ROLLOVER_MAX_AGE]}${
phase[PHASE_ROLLOVER_MAX_AGE_UNITS]
}`;
- } else if (isNumber(phase[PHASE_ROLLOVER_MAX_SIZE_STORED])) {
+ }
+ if (isNumber(phase[PHASE_ROLLOVER_MAX_SIZE_STORED])) {
if (phase[PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS] === MAX_SIZE_TYPE_DOCUMENT) {
esPhase.actions.rollover.max_docs = phase[PHASE_ROLLOVER_MAX_SIZE_STORED];
} else {
@@ -246,7 +247,6 @@ export const phaseToES = (state, phase) => {
}
}
}
-
if (phase[PHASE_NODE_ATTRS]) {
esPhase.actions.allocate = {
include: {}, // TODO: this seems to be a constant, confirm?
From 3c180940434d901f250bc6b0a4f91a45e286631a Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Tue, 30 Oct 2018 08:22:06 -0400
Subject: [PATCH 079/102] removing names of covered indices from policy table
---
.../policy_table/components/policy_table/policy_table.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js
index 1ed6d7ab44863..658a4710d885f 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/policy_table.js
@@ -124,7 +124,7 @@ export class PolicyTableUi extends Component {
} else if (fieldName === 'coveredIndices' && value) {
return (
- {value.length} ({value.join(', ')})
+ {value.length}
);
} else if (fieldName === 'modified_date' && value) {
From b14de85bf571a450b2ee3de18b88f0c4cadb964c Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Wed, 31 Oct 2018 10:23:42 -0400
Subject: [PATCH 080/102] changing minimum_age to min_age
---
.../public/store/selectors/lifecycle.js | 2 +-
.../public/store/selectors/policies.js | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
index a6c24a2d90596..f70452ef15873 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
@@ -149,7 +149,7 @@ export const getLifecycle = state => {
// These seem to be constants
// TODO: verify this assumption
if (phaseName === PHASE_HOT) {
- accum[phaseName].minimum_age = '0s';
+ accum[phaseName].min_age = '0s';
}
if (phaseName === PHASE_DELETE) {
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
index 6f87e542dd9f1..d41ef602b8430 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
@@ -136,12 +136,12 @@ export const phaseFromES = (phase, phaseName, defaultPolicy) => {
policy[PHASE_ENABLED] = true;
policy[PHASE_ROLLOVER_ENABLED] = false;
- if (phase.minimum_age) {
- if (phaseName === PHASE_WARM && phase.minimum_age === '0ms') {
+ if (phase.min_age) {
+ if (phaseName === PHASE_WARM && phase.min_age === '0ms') {
policy[WARM_PHASE_ON_ROLLOVER] = true;
} else {
const { size: minAge, units: minAgeUnits } = splitSizeAndUnits(
- phase.minimum_age
+ phase.min_age
);
policy[PHASE_ROLLOVER_MINIMUM_AGE] = minAge;
policy[PHASE_ROLLOVER_MINIMUM_AGE_UNITS] = minAgeUnits;
@@ -224,7 +224,7 @@ export const phaseToES = (state, phase) => {
}
if (isNumber(phase[PHASE_ROLLOVER_MINIMUM_AGE])) {
- esPhase.minimum_age = `${phase[PHASE_ROLLOVER_MINIMUM_AGE]}${phase[PHASE_ROLLOVER_MINIMUM_AGE_UNITS]}`;
+ esPhase.min_age = `${phase[PHASE_ROLLOVER_MINIMUM_AGE]}${phase[PHASE_ROLLOVER_MINIMUM_AGE_UNITS]}`;
}
esPhase.actions = {};
From c71dd61eca243ba6f9c0e7ae98a7c8fa11e9bb35 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Thu, 1 Nov 2018 21:35:57 -0400
Subject: [PATCH 081/102] first pass at index lifecycle extensions
---
.../index_lifecycle_management/index.js | 21 +++--
.../index_lifecycle_data.js | 22 +++++
.../components/index_lifecycle_summary.js | 94 +++++++++++++++++++
.../public/index.js | 1 +
.../register_index_lifecycle_summary.js | 13 +++
.../lib/error_wrappers/wrap_es_error.js | 2 +-
.../license_pre_routing_factory.js | 7 +-
.../api/indices/register_bootstrap_route.js | 8 +-
.../indices/register_get_affected_route.js | 16 ++--
.../api/lifecycle/register_create_route.js | 10 +-
.../api/nodes/register_details_route.js | 8 +-
.../routes/api/nodes/register_list_route.js | 8 +-
.../api/policies/register_delete_route.js | 11 +--
.../api/policies/register_fetch_route.js | 10 +-
.../api/templates/register_fetch_route.js | 8 +-
.../api/templates/register_get_route.js | 8 +-
x-pack/plugins/index_management/index.js | 3 +-
.../index_management/index_management_data.js | 13 +++
.../plugins/index_management/public/index.js | 1 +
.../public/index_management_extensions.js | 21 +++++
.../detail_panel/summary/summary.js | 58 ++++++++++--
.../routes/api/indices/register_list_route.js | 9 +-
.../api/indices/register_reload_route.js | 8 +-
23 files changed, 290 insertions(+), 70 deletions(-)
create mode 100644 x-pack/plugins/index_lifecycle_management/index_lifecycle_data.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_summary.js
create mode 100644 x-pack/plugins/index_management/index_management_data.js
create mode 100644 x-pack/plugins/index_management/public/index_management_extensions.js
diff --git a/x-pack/plugins/index_lifecycle_management/index.js b/x-pack/plugins/index_lifecycle_management/index.js
index 2824f8e345d50..f5bc1e4745852 100644
--- a/x-pack/plugins/index_lifecycle_management/index.js
+++ b/x-pack/plugins/index_lifecycle_management/index.js
@@ -4,9 +4,6 @@
* you may not use this file except in compliance with the Elastic License.
*/
-
-
-
import { resolve } from 'path';
import { registerTemplatesRoutes } from './server/routes/api/templates';
import { registerNodesRoutes } from './server/routes/api/nodes';
@@ -15,16 +12,14 @@ import { registerLifecycleRoutes } from './server/routes/api/lifecycle';
import { registerIndicesRoutes } from './server/routes/api/indices';
import { registerLicenseChecker } from './server/lib/register_license_checker';
import { PLUGIN } from './common/constants';
-
-export function indexLifecycleManagement(kibana) {
+import { indexLifecycleDataEnricher } from './index_lifecycle_data';
+export function indexLifecycleManagement(kibana) {
return new kibana.Plugin({
id: PLUGIN.ID,
publicDir: resolve(__dirname, 'public'),
- require: ['kibana', 'elasticsearch', 'xpack_main'],
+ require: ['kibana', 'elasticsearch', 'xpack_main', 'index_management'],
uiExports: {
- managementSections: [
- 'plugins/index_lifecycle_management',
- ]
+ managementSections: ['plugins/index_lifecycle_management'],
},
init: function (server) {
registerLicenseChecker(server);
@@ -33,6 +28,12 @@ export function indexLifecycleManagement(kibana) {
registerPoliciesRoutes(server);
registerLifecycleRoutes(server);
registerIndicesRoutes(server);
- }
+ if (
+ server.plugins.index_management &&
+ server.plugins.index_management.addIndexManagementDataEnricher
+ ) {
+ server.plugins.index_management.addIndexManagementDataEnricher(indexLifecycleDataEnricher);
+ }
+ },
});
}
diff --git a/x-pack/plugins/index_lifecycle_management/index_lifecycle_data.js b/x-pack/plugins/index_lifecycle_management/index_lifecycle_data.js
new file mode 100644
index 0000000000000..57b90204ce224
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/index_lifecycle_data.js
@@ -0,0 +1,22 @@
+/*
+ * 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 indexLifecycleDataEnricher = async (indicesList, callWithRequest) => {
+ if (!indicesList || !indicesList.length) {
+ return;
+ }
+ const params = {
+ path: '/*/_ilm/explain',
+ method: 'GET',
+ };
+ const { indices: ilmIndicesData } = await callWithRequest('transport.request', params);
+ return indicesList.map(index => {
+ return {
+ ...index,
+ ilm: { ...(ilmIndicesData[index.name] || {}) },
+ };
+ });
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js b/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js
new file mode 100644
index 0000000000000..a64efb148c0de
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js
@@ -0,0 +1,94 @@
+/*
+ * 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, { Component, Fragment } from 'react';
+
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiDescriptionList,
+ EuiDescriptionListTitle,
+ EuiDescriptionListDescription,
+ EuiSpacer,
+ EuiTitle
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+const HEADERS = {
+ policy: i18n.translate('xpack.indexLifecycleMgmt.summary.headers.lifecyclePolicyHeader', {
+ defaultMessage: 'Lifecycle policy',
+ }),
+ phase: i18n.translate('xpack.indexLifecycleMgmt.summary.headers.currentPhaseHeader', {
+ defaultMessage: 'Current phase',
+ }),
+ action: i18n.translate('xpack.idxMgmt.indexLifecycleMgmtSummary.headers.nextActionHeader', {
+ defaultMessage: 'Next action',
+ }),
+ action_time: i18n.translate('xpack.idxMgmt.indexLifecycleMgmtSummary.headers.nextActionTimeHeader', {
+ defaultMessage: 'Next action time',
+ }),
+ failed_step: i18n.translate('xpack.idxMgmt.indexLifecycleMgmtSummary.headers.failedStepHeader', {
+ defaultMessage: 'Failed step',
+ }),
+ step_info: i18n.translate('xpack.idxMgmt.indexLifecycleMgmtSummary.headers.errorInfoHeader', {
+ defaultMessage: 'Error info',
+ }),
+};
+export class IndexLifecycleSummary extends Component {
+
+ buildRows() {
+ const { index: { ilm = {} } } = this.props;
+ const rows = {
+ left: [],
+ right: []
+ };
+ Object.keys(HEADERS).forEach((fieldName, arrayIndex) => {
+ const value = ilm[fieldName];
+ const content = fieldName === 'step_info' ? (
+ `${value.type}: ${value.reason}`
+ ) : value;
+ const cell = [
+
+ {HEADERS[fieldName]}:
+ ,
+
+ {content}
+
+ ];
+ if (arrayIndex % 2 === 0) {
+ rows.left.push(cell);
+ } else {
+ rows.right.push(cell);
+ }
+ });
+ return rows;
+ }
+
+ render() {
+ const { index: { ilm = {} } } = this.props;
+ if (!ilm.managed) {
+ return null;
+ }
+ const { left, right } = this.buildRows();
+ return (
+
+ Index lifecycle management
+
+
+
+
+ {left}
+
+
+
+
+ {right}
+
+
+
+
+ );
+ }
+}
\ No newline at end of file
diff --git a/x-pack/plugins/index_lifecycle_management/public/index.js b/x-pack/plugins/index_lifecycle_management/public/index.js
index ccde49edbdf5d..235137923b819 100644
--- a/x-pack/plugins/index_lifecycle_management/public/index.js
+++ b/x-pack/plugins/index_lifecycle_management/public/index.js
@@ -6,3 +6,4 @@
import './register_management_section';
import './register_routes';
+import './register_index_lifecycle_summary';
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_summary.js b/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_summary.js
new file mode 100644
index 0000000000000..cd5a262b1635a
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_summary.js
@@ -0,0 +1,13 @@
+/*
+ * 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 { addSummaryExtension } from '../../index_management/public/index_management_extensions';
+import { IndexLifecycleSummary } from './components/index_lifecycle_summary';
+addSummaryExtension((index) => {
+ return ;
+});
+
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.js
index 6ac4d50c7e0fe..9f1328219bab2 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.js
@@ -20,7 +20,7 @@ export function wrapEsError(err, statusCodeToMessageMap = {}) {
// 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.wrap(err, err.statusCode);
+ return Boom.boomify(err, err.statusCode);
}
// Otherwise, use the custom message to create a Boom error response and
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js
index b3720ab265393..abfc7fc24dcc3 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js
@@ -12,16 +12,15 @@ export const licensePreRoutingFactory = once((server) => {
const xpackMainPlugin = server.plugins.xpack_main;
// License checking and enable/disable logic
- function licensePreRouting(request, reply) {
+ function licensePreRouting() {
const licenseCheckResults = xpackMainPlugin.info.feature(PLUGIN.ID).getLicenseCheckResults();
if (!licenseCheckResults.isAvailable) {
const error = new Error(licenseCheckResults.message);
const statusCode = 403;
const wrappedError = wrapCustomError(error, statusCode);
- reply(wrappedError);
- } else {
- reply();
+ return wrappedError;
}
+ return null;
}
return licensePreRouting;
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_bootstrap_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_bootstrap_route.js
index dcd053e096c52..ad449101cb4f5 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_bootstrap_route.js
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_bootstrap_route.js
@@ -29,18 +29,18 @@ export function registerBootstrapRoute(server) {
server.route({
path: '/api/index_lifecycle_management/indices/bootstrap',
method: 'POST',
- handler: async (request, reply) => {
+ handler: async (request) => {
const callWithRequest = callWithRequestFactory(server, request);
try {
const response = await bootstrap(callWithRequest, request.payload);
- reply(response);
+ return response;
} catch (err) {
if (isEsError(err)) {
- return reply(wrapEsError(err));
+ return wrapEsError(err);
}
- reply(wrapUnknownError(err));
+ return wrapUnknownError(err);
}
},
config: {
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_get_affected_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_get_affected_route.js
index 8f60bffb94b5a..ed5b6b09db16b 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_get_affected_route.js
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_get_affected_route.js
@@ -72,7 +72,7 @@ export function registerGetAffectedRoute(server) {
path:
'/api/index_lifecycle_management/indices/affected/{indexTemplateName}',
method: 'GET',
- handler: async (request, reply) => {
+ handler: async (request) => {
const callWithRequest = callWithRequestFactory(server, request);
try {
@@ -80,13 +80,13 @@ export function registerGetAffectedRoute(server) {
callWithRequest,
request.params.indexTemplateName,
);
- reply(response);
+ return response;
} catch (err) {
if (isEsError(err)) {
- return reply(wrapEsError(err));
+ return wrapEsError(err);
}
- reply(wrapUnknownError(err));
+ return wrapUnknownError(err);
}
},
config: {
@@ -98,7 +98,7 @@ export function registerGetAffectedRoute(server) {
path:
'/api/index_lifecycle_management/indices/affected/{indexTemplateName}/{policyName}',
method: 'GET',
- handler: async (request, reply) => {
+ handler: async (request) => {
const callWithRequest = callWithRequestFactory(server, request);
try {
@@ -107,13 +107,13 @@ export function registerGetAffectedRoute(server) {
request.params.indexTemplateName,
request.params.policyName
);
- reply(response);
+ return response;
} catch (err) {
if (isEsError(err)) {
- return reply(wrapEsError(err));
+ return wrapEsError(err);
}
- reply(wrapUnknownError(err));
+ return wrapUnknownError(err);
}
},
config: {
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_create_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_create_route.js
index ca1a021c6100a..8aa93e3540243 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_create_route.js
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/lifecycle/register_create_route.js
@@ -20,7 +20,7 @@ async function createLifecycle(callWithRequest, lifecycle) {
};
const params = {
method: 'PUT',
- path: `/_ilm/${lifecycle.name}`,
+ path: `/_ilm/policy/${lifecycle.name}`,
ignore: [ 404 ],
body,
};
@@ -35,18 +35,18 @@ export function registerCreateRoute(server) {
server.route({
path: '/api/index_lifecycle_management/lifecycle',
method: 'POST',
- handler: async (request, reply) => {
+ handler: async (request) => {
const callWithRequest = callWithRequestFactory(server, request);
try {
const response = await createLifecycle(callWithRequest, request.payload.lifecycle);
- reply(response);
+ return response;
} catch (err) {
if (isEsError(err)) {
- return reply(wrapEsError(err));
+ return wrapEsError(err);
}
- reply(wrapUnknownError(err));
+ return wrapUnknownError(err);
}
},
config: {
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.js
index 6cd882caf73a0..9547e66c73dc3 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.js
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.js
@@ -43,19 +43,19 @@ export function registerDetailsRoute(server) {
server.route({
path: '/api/index_lifecycle_management/nodes/{nodeAttrs}/details',
method: 'GET',
- handler: async (request, reply) => {
+ handler: async (request) => {
const callWithRequest = callWithRequestFactory(server, request);
try {
const stats = await fetchNodeStats(callWithRequest);
const response = findMatchingNodes(stats, request.params.nodeAttrs);
- reply(response);
+ return response;
} catch (err) {
if (isEsError(err)) {
- return reply(wrapEsError(err));
+ return wrapEsError(err);
}
- reply(wrapUnknownError(err));
+ return wrapUnknownError(err);
}
},
config: {
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.js
index 8e92e6570edcf..40525b45f5566 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.js
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.js
@@ -42,19 +42,19 @@ export function registerListRoute(server) {
server.route({
path: '/api/index_lifecycle_management/nodes/list',
method: 'GET',
- handler: async (request, reply) => {
+ handler: async (request) => {
const callWithRequest = callWithRequestFactory(server, request);
try {
const stats = await fetchNodeStats(callWithRequest);
const response = convertStatsIntoList(stats);
- reply(response);
+ return response;
} catch (err) {
if (isEsError(err)) {
- return reply(wrapEsError(err));
+ return wrapEsError(err);
}
- reply(wrapUnknownError(err));
+ return wrapUnknownError(err);
}
},
config: {
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.js
index bd69b3b93531c..1e06bf99f6db4 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.js
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.js
@@ -9,11 +9,10 @@ import { isEsErrorFactory } from '../../../lib/is_es_error_factory';
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory';
-
async function deletePolicies(policyNames, callWithRequest) {
const params = {
method: 'DELETE',
- path: `/_ilm/${policyNames}`,
+ path: `/_ilm/policy/${policyNames}`,
// we allow 404 since they may have no policies
ignore: [ 404 ]
};
@@ -28,17 +27,17 @@ export function registerDeleteRoute(server) {
server.route({
path: '/api/index_lifecycle_management/policies/{policyNames}',
method: 'DELETE',
- handler: async (request, reply) => {
+ handler: async (request) => {
const callWithRequest = callWithRequestFactory(server, request);
const { policyNames } = request.params;
try {
await deletePolicies(policyNames, callWithRequest);
- reply();
+ return;
} catch (err) {
if (isEsError(err)) {
- return reply(wrapEsError(err));
+ return wrapEsError(err);
}
- reply(wrapUnknownError(err));
+ return wrapUnknownError(err);
}
},
config: {
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.js
index 22387ec11dde3..df2c0096cddff 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.js
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.js
@@ -26,7 +26,7 @@ function formatPolicies(policiesMap) {
async function fetchPolicies(callWithRequest) {
const params = {
method: 'GET',
- path: '/_ilm',
+ path: '/_ilm/policy',
// we allow 404 since they may have no policies
ignore: [ 404 ]
};
@@ -60,7 +60,7 @@ export function registerFetchRoute(server) {
server.route({
path: '/api/index_lifecycle_management/policies',
method: 'GET',
- handler: async (request, reply) => {
+ handler: async (request) => {
const callWithRequest = callWithRequestFactory(server, request);
const { withIndices } = request.query;
try {
@@ -68,13 +68,13 @@ export function registerFetchRoute(server) {
if (withIndices) {
await addCoveredIndices(policiesMap, callWithRequest);
}
- reply(formatPolicies(policiesMap));
+ return formatPolicies(policiesMap);
} catch (err) {
if (isEsError(err)) {
- return reply(wrapEsError(err));
+ return wrapEsError(err);
}
- reply(wrapUnknownError(err));
+ return wrapUnknownError(err);
}
},
config: {
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.js
index 1a4c5529b8da8..d7fd8c83a2c98 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.js
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_fetch_route.js
@@ -61,19 +61,19 @@ export function registerFetchRoute(server) {
server.route({
path: '/api/index_lifecycle_management/templates',
method: 'GET',
- handler: async (request, reply) => {
+ handler: async (request) => {
const callWithRequest = callWithRequestFactory(server, request);
try {
const hits = await fetchTemplates(callWithRequest);
const templates = await formatTemplates(hits, callWithRequest);
- reply(templates);
+ return templates;
} catch (err) {
if (isEsError(err)) {
- return reply(wrapEsError(err));
+ return wrapEsError(err);
}
- reply(wrapUnknownError(err));
+ return wrapUnknownError(err);
}
},
config: {
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_get_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_get_route.js
index 690960e953c8c..ad24160fe798f 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_get_route.js
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/templates/register_get_route.js
@@ -30,19 +30,19 @@ export function registerGetRoute(server) {
server.route({
path: '/api/index_lifecycle_management/template/{templateName}',
method: 'GET',
- handler: async (request, reply) => {
+ handler: async (request) => {
const callWithRequest = callWithRequestFactory(server, request);
const templateName = request.params.templateName;
try {
const template = await fetchTemplate(callWithRequest, templateName);
- reply(template[templateName]);
+ return template[templateName];
} catch (err) {
if (isEsError(err)) {
- return reply(wrapEsError(err));
+ return wrapEsError(err);
}
- reply(wrapUnknownError(err));
+ return wrapUnknownError(err);
}
},
config: {
diff --git a/x-pack/plugins/index_management/index.js b/x-pack/plugins/index_management/index.js
index 4408428364b83..c48eaa6ba15ca 100644
--- a/x-pack/plugins/index_management/index.js
+++ b/x-pack/plugins/index_management/index.js
@@ -11,7 +11,7 @@ import { registerSettingsRoutes } from './server/routes/api/settings';
import { registerStatsRoute } from './server/routes/api/stats';
import { registerLicenseChecker } from './server/lib/register_license_checker';
import { PLUGIN } from './common/constants';
-
+import { addIndexManagementDataEnricher } from "./index_management_data";
export function indexManagement(kibana) {
return new kibana.Plugin({
id: PLUGIN.ID,
@@ -24,6 +24,7 @@ export function indexManagement(kibana) {
]
},
init: function (server) {
+ server.expose('addIndexManagementDataEnricher', addIndexManagementDataEnricher);
registerLicenseChecker(server);
registerIndicesRoutes(server);
registerSettingsRoutes(server);
diff --git a/x-pack/plugins/index_management/index_management_data.js b/x-pack/plugins/index_management/index_management_data.js
new file mode 100644
index 0000000000000..022ab9b6da5d4
--- /dev/null
+++ b/x-pack/plugins/index_management/index_management_data.js
@@ -0,0 +1,13 @@
+/*
+ * 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.
+ */
+
+const indexManagementDataEnrichers = [];
+export const addIndexManagementDataEnricher = (provider) => {
+ indexManagementDataEnrichers.push(provider);
+};
+export const getIndexManagementDataEnrichers = () => {
+ return indexManagementDataEnrichers;
+};
\ No newline at end of file
diff --git a/x-pack/plugins/index_management/public/index.js b/x-pack/plugins/index_management/public/index.js
index ccde49edbdf5d..d52bf02b82f65 100644
--- a/x-pack/plugins/index_management/public/index.js
+++ b/x-pack/plugins/index_management/public/index.js
@@ -6,3 +6,4 @@
import './register_management_section';
import './register_routes';
+import './index_management_extensions';
diff --git a/x-pack/plugins/index_management/public/index_management_extensions.js b/x-pack/plugins/index_management/public/index_management_extensions.js
new file mode 100644
index 0000000000000..eb14abd7681bd
--- /dev/null
+++ b/x-pack/plugins/index_management/public/index_management_extensions.js
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+const summaryExtensions = [];
+export const addSummaryExtension = (summaryExtension)=> {
+ summaryExtensions.push(summaryExtension);
+};
+export const getSummaryExtensions = () => {
+ return summaryExtensions;
+};
+const actionExtensions = [];
+export const addActionExtension = (actionExtension)=> {
+ actionExtensions.push(actionExtension);
+};
+export const getActionExtensions = () => {
+ return actionExtensions;
+};
+
diff --git a/x-pack/plugins/index_management/public/sections/index_list/components/detail_panel/summary/summary.js b/x-pack/plugins/index_management/public/sections/index_list/components/detail_panel/summary/summary.js
index 7346ab6650f65..b0cccd21fe829 100644
--- a/x-pack/plugins/index_management/public/sections/index_list/components/detail_panel/summary/summary.js
+++ b/x-pack/plugins/index_management/public/sections/index_list/components/detail_panel/summary/summary.js
@@ -4,16 +4,21 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
+import React, { Fragment } from 'react';
import { i18n } from '@kbn/i18n';
import { healthToColor } from '../../../../../services';
import {
+ EuiFlexGroup,
+ EuiFlexItem,
EuiHealth,
EuiDescriptionList,
+ EuiHorizontalRule,
EuiDescriptionListTitle,
EuiDescriptionListDescription,
+ EuiSpacer,
+ EuiTitle
} from '@elastic/eui';
-
+import { getSummaryExtensions } from '../../../../../index_management_extensions';
const HEADERS = {
health: i18n.translate('xpack.idxMgmt.summary.headers.healthHeader', {
defaultMessage: 'Health',
@@ -42,15 +47,32 @@ const HEADERS = {
};
export class Summary extends React.PureComponent {
+ getAdditionalContent() {
+ const { index } = this.props;
+ const extensions = getSummaryExtensions();
+ console.log(extensions);
+ return extensions.map((summaryExtension) => {
+ return (
+
+
+ { summaryExtension(index) }
+
+ );
+ });
+ }
buildRows() {
const { index } = this.props;
- return Object.keys(HEADERS).map(fieldName => {
+ const rows = {
+ left: [],
+ right: []
+ };
+ Object.keys(HEADERS).forEach((fieldName, arrayIndex) => {
const value = index[fieldName];
const content =
fieldName === "health" ? (
{value}
) : value;
- return [
+ const cell = [
{HEADERS[fieldName]}:
,
@@ -58,14 +80,36 @@ export class Summary extends React.PureComponent {
{content}
];
+ if (arrayIndex % 2 === 0) {
+ rows.left.push(cell);
+ } else {
+ rows.right.push(cell);
+ }
});
+ return rows;
}
render() {
+ const { left, right } = this.buildRows();
+ const additionalContent = this.getAdditionalContent();
return (
-
- {this.buildRows()}
-
+
+ General
+
+
+
+
+ {left}
+
+
+
+
+ {right}
+
+
+
+ { additionalContent }
+
);
}
}
diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_list_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_list_route.js
index af2a03f5bc4aa..879424d9e7948 100644
--- a/x-pack/plugins/index_management/server/routes/api/indices/register_list_route.js
+++ b/x-pack/plugins/index_management/server/routes/api/indices/register_list_route.js
@@ -8,7 +8,7 @@ import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
import { isEsErrorFactory } from '../../../lib/is_es_error_factory';
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory';
-
+import { getIndexManagementDataEnrichers } from '../../../../index_management_data';
function formatHits(hits) {
return hits.map(hit => {
return {
@@ -46,7 +46,12 @@ export function registerListRoute(server) {
try {
const hits = await fetchIndices(callWithRequest);
- const response = formatHits(hits);
+ let response = formatHits(hits);
+ const dataEnrichers = getIndexManagementDataEnrichers();
+ for (let i = 0; i < dataEnrichers.length; i++) {
+ const dataEnricher = dataEnrichers[i];
+ response = await dataEnricher(response, callWithRequest);
+ }
return response;
} catch (err) {
if (isEsError(err)) {
diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_reload_route.js b/x-pack/plugins/index_management/server/routes/api/indices/register_reload_route.js
index 8aa486be06f37..98916f40e6924 100644
--- a/x-pack/plugins/index_management/server/routes/api/indices/register_reload_route.js
+++ b/x-pack/plugins/index_management/server/routes/api/indices/register_reload_route.js
@@ -8,6 +8,7 @@ import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
import { isEsErrorFactory } from '../../../lib/is_es_error_factory';
import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory';
+import { getIndexManagementDataEnrichers } from '../../../../index_management_data';
function getIndexNamesFromPayload(payload) {
return payload.indexNames || [];
@@ -52,7 +53,12 @@ export function registerReloadRoute(server) {
try {
const hits = await fetchIndices(callWithRequest, indexNames);
- const response = formatHits(hits);
+ let response = formatHits(hits);
+ const dataEnrichers = getIndexManagementDataEnrichers();
+ for (let i = 0; i < dataEnrichers.length; i++) {
+ const dataEnricher = dataEnrichers[i];
+ response = await dataEnricher(response, callWithRequest);
+ }
return response;
} catch (err) {
if (isEsError(err)) {
From bfffab0c61fa0bac9fa0ac33a8e670ebaed9adc0 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Fri, 2 Nov 2018 08:31:58 -0400
Subject: [PATCH 082/102] adding retry button for ilm covered index that is in
error
---
.../index_lifecycle_management/index.js | 4 +-
.../public/api/index.js | 25 +++++----
.../components/index_lifecycle_summary.js | 16 ++++--
.../public/index.js | 1 +
.../register_index_lifecycle_actions.js | 31 +++++++++++
.../routes/api/{indices => index}/index.js | 2 +-
.../register_bootstrap_route.js | 0
.../register_get_affected_route.js | 0
.../register_index_routes.js} | 4 +-
.../routes/api/index/register_retry_route.js | 52 +++++++++++++++++++
.../public/index_management_extensions.js | 1 +
.../index_actions_context_menu.container.js | 12 +++--
.../index_actions_context_menu.js | 19 +++++++
.../index_management/public/services/api.js | 3 ++
.../public/store/actions/extension_action.js | 20 +++++++
.../public/store/actions/index.js | 1 +
.../public/store/selectors/index.js | 6 ++-
17 files changed, 176 insertions(+), 21 deletions(-)
create mode 100644 x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_actions.js
rename x-pack/plugins/index_lifecycle_management/server/routes/api/{indices => index}/index.js (78%)
rename x-pack/plugins/index_lifecycle_management/server/routes/api/{indices => index}/register_bootstrap_route.js (100%)
rename x-pack/plugins/index_lifecycle_management/server/routes/api/{indices => index}/register_get_affected_route.js (100%)
rename x-pack/plugins/index_lifecycle_management/server/routes/api/{indices/register_indices_routes.js => index/register_index_routes.js} (77%)
create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.js
create mode 100644 x-pack/plugins/index_management/public/store/actions/extension_action.js
diff --git a/x-pack/plugins/index_lifecycle_management/index.js b/x-pack/plugins/index_lifecycle_management/index.js
index f5bc1e4745852..4c666fffde158 100644
--- a/x-pack/plugins/index_lifecycle_management/index.js
+++ b/x-pack/plugins/index_lifecycle_management/index.js
@@ -9,7 +9,7 @@ import { registerTemplatesRoutes } from './server/routes/api/templates';
import { registerNodesRoutes } from './server/routes/api/nodes';
import { registerPoliciesRoutes } from './server/routes/api/policies';
import { registerLifecycleRoutes } from './server/routes/api/lifecycle';
-import { registerIndicesRoutes } from './server/routes/api/indices';
+import { registerIndexRoutes } from './server/routes/api/index';
import { registerLicenseChecker } from './server/lib/register_license_checker';
import { PLUGIN } from './common/constants';
import { indexLifecycleDataEnricher } from './index_lifecycle_data';
@@ -27,7 +27,7 @@ export function indexLifecycleManagement(kibana) {
registerNodesRoutes(server);
registerPoliciesRoutes(server);
registerLifecycleRoutes(server);
- registerIndicesRoutes(server);
+ registerIndexRoutes(server);
if (
server.plugins.index_management &&
server.plugins.index_management.addIndexManagementDataEnricher
diff --git a/x-pack/plugins/index_lifecycle_management/public/api/index.js b/x-pack/plugins/index_lifecycle_management/public/api/index.js
index 542acfe8e987b..8db47a8e6380c 100644
--- a/x-pack/plugins/index_lifecycle_management/public/api/index.js
+++ b/x-pack/plugins/index_lifecycle_management/public/api/index.js
@@ -3,30 +3,33 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-
import chrome from 'ui/chrome';
+
let httpClient;
export const setHttpClient = (client) => {
httpClient = client;
};
+const getHttpClient = () => {
+ return httpClient;
+};
const apiPrefix = chrome.addBasePath('/api/index_lifecycle_management');
-export async function loadNodes() {
+export async function loadNodes(httpClient = getHttpClient()) {
const response = await httpClient.get(`${apiPrefix}/nodes/list`);
return response.data;
}
-export async function loadNodeDetails(selectedNodeAttrs) {
+export async function loadNodeDetails(selectedNodeAttrs, httpClient = getHttpClient()) {
const response = await httpClient.get(`${apiPrefix}/nodes/${selectedNodeAttrs}/details`);
return response.data;
}
-export async function loadIndexTemplates() {
+export async function loadIndexTemplates(httpClient = getHttpClient()) {
const response = await httpClient.get(`${apiPrefix}/templates`);
return response.data;
}
-export async function loadIndexTemplate(templateName) {
+export async function loadIndexTemplate(templateName, httpClient = getHttpClient()) {
if (!templateName) {
return {};
}
@@ -34,26 +37,30 @@ export async function loadIndexTemplate(templateName) {
return response.data;
}
-export async function loadPolicies(withIndices) {
+export async function loadPolicies(withIndices, httpClient = getHttpClient()) {
const response = await httpClient.get(`${apiPrefix}/policies${ withIndices ? '?withIndices=true' : ''}`);
return response.data;
}
-export async function deletePolicy(policyName) {
+export async function deletePolicy(policyName, httpClient = getHttpClient()) {
const response = await httpClient.delete(`${apiPrefix}/policies/${policyName}`);
return response.data;
}
-export async function saveLifecycle(lifecycle) {
+export async function saveLifecycle(lifecycle, httpClient = getHttpClient()) {
const response = await httpClient.post(`${apiPrefix}/lifecycle`, { lifecycle });
return response.data;
}
-export async function getAffectedIndices(indexTemplateName, policyName) {
+export async function getAffectedIndices(indexTemplateName, policyName, httpClient = getHttpClient()) {
const path = policyName
? `${apiPrefix}/indices/affected/${indexTemplateName}/${encodeURIComponent(policyName)}`
: `${apiPrefix}/indices/affected/${indexTemplateName}`;
const response = await httpClient.get(path);
return response.data;
}
+export const retryLifecycleForIndex = async (indexNames, httpClient = getHttpClient()) => {
+ const response = await httpClient.post(`${apiPrefix}/index/retry`, { indexNames });
+ return response.data;
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js b/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js
index a64efb148c0de..4e38932dab42d 100644
--- a/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js
+++ b/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js
@@ -5,7 +5,7 @@
*/
import React, { Component, Fragment } from 'react';
-
+import moment from 'moment-timezone';
import {
EuiFlexGroup,
EuiFlexItem,
@@ -46,9 +46,17 @@ export class IndexLifecycleSummary extends Component {
};
Object.keys(HEADERS).forEach((fieldName, arrayIndex) => {
const value = ilm[fieldName];
- const content = fieldName === 'step_info' ? (
- `${value.type}: ${value.reason}`
- ) : value;
+ let content;
+ if (fieldName === 'step_info') {
+ if (value) {
+ content = `${value.type}: ${value.reason}`;
+ }
+ } else if (fieldName === 'action_time') {
+ content = moment(value).format('YYYY-MM-DD HH:mm:ss');
+ } else {
+ content = value;
+ }
+ content = content || '-';
const cell = [
{HEADERS[fieldName]}:
diff --git a/x-pack/plugins/index_lifecycle_management/public/index.js b/x-pack/plugins/index_lifecycle_management/public/index.js
index 235137923b819..867ee0e3ef913 100644
--- a/x-pack/plugins/index_lifecycle_management/public/index.js
+++ b/x-pack/plugins/index_lifecycle_management/public/index.js
@@ -7,3 +7,4 @@
import './register_management_section';
import './register_routes';
import './register_index_lifecycle_summary';
+import './register_index_lifecycle_actions';
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_actions.js b/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_actions.js
new file mode 100644
index 0000000000000..f37e06f8a8c4e
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_actions.js
@@ -0,0 +1,31 @@
+/*
+ * 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 { every } from 'lodash';
+import { i18n } from '@kbn/i18n';
+import { addActionExtension } from '../../index_management/public/index_management_extensions';
+import { retryLifecycleForIndex } from './api';
+addActionExtension((indices) => {
+ const allHaveErrors = every(indices, (index) => {
+ return (index.ilm && index.ilm.failed_step);
+ });
+ if (!allHaveErrors) {
+ return null;
+ }
+ const indexNames = indices.map(({ name }) => name);
+ return {
+ requestMethod: retryLifecycleForIndex,
+ indexNames: [indexNames],
+ buttonLabel: i18n.translate('xpack.idxMgmt.retryIndexLifecycleActionButtonLabel', {
+ defaultMessage: 'Retry lifecycle',
+ }),
+ successMessage: i18n.translate('xpack.idxMgmt.retryIndexLifecycleAction.successfullyRetriedLifecycleMessage', {
+ defaultMessage: 'Successfully called retry lifecycle for: [{indexNames}]',
+ values: { indexNames: indexNames.join(', ') }
+ }),
+ };
+});
+
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/index.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/index.js
similarity index 78%
rename from x-pack/plugins/index_lifecycle_management/server/routes/api/indices/index.js
rename to x-pack/plugins/index_lifecycle_management/server/routes/api/index/index.js
index 915fb695bb468..82fb2e3b2a372 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/index.js
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/index.js
@@ -4,4 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { registerIndicesRoutes } from './register_indices_routes';
+export { registerIndexRoutes } from './register_index_routes';
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_bootstrap_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_bootstrap_route.js
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_bootstrap_route.js
rename to x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_bootstrap_route.js
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_get_affected_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_get_affected_route.js
similarity index 100%
rename from x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_get_affected_route.js
rename to x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_get_affected_route.js
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_indices_routes.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_index_routes.js
similarity index 77%
rename from x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_indices_routes.js
rename to x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_index_routes.js
index 1f94eb13d125e..12007e778a989 100644
--- a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/register_indices_routes.js
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_index_routes.js
@@ -6,8 +6,10 @@
import { registerBootstrapRoute } from './register_bootstrap_route';
import { registerGetAffectedRoute } from './register_get_affected_route';
+import { registerRetryRoute } from './register_retry_route';
-export function registerIndicesRoutes(server) {
+export function registerIndexRoutes(server) {
registerBootstrapRoute(server);
registerGetAffectedRoute(server);
+ registerRetryRoute(server);
}
diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.js
new file mode 100644
index 0000000000000..97d51022374a6
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/index/register_retry_route.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+import { callWithRequestFactory } from '../../../lib/call_with_request_factory';
+import { isEsErrorFactory } from '../../../lib/is_es_error_factory';
+import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers';
+import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory';
+
+async function retryLifecycle(callWithRequest, indexNames) {
+ const responses = [];
+ for (let i = 0; i < indexNames.length; i++) {
+ const indexName = indexNames[i];
+ const params = {
+ method: 'POST',
+ path: `/${indexName}/_ilm/retry`,
+ ignore: [ 404 ],
+ };
+
+ responses.push(callWithRequest('transport.request', params));
+ }
+ return Promise.all(responses);
+}
+
+export function registerRetryRoute(server) {
+ const isEsError = isEsErrorFactory(server);
+ const licensePreRouting = licensePreRoutingFactory(server);
+
+ server.route({
+ path: '/api/index_lifecycle_management/index/retry',
+ method: 'POST',
+ handler: async (request) => {
+ 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 ]
+ }
+ });
+}
diff --git a/x-pack/plugins/index_management/public/index_management_extensions.js b/x-pack/plugins/index_management/public/index_management_extensions.js
index eb14abd7681bd..192b75d4f4446 100644
--- a/x-pack/plugins/index_management/public/index_management_extensions.js
+++ b/x-pack/plugins/index_management/public/index_management_extensions.js
@@ -19,3 +19,4 @@ export const getActionExtensions = () => {
return actionExtensions;
};
+
diff --git a/x-pack/plugins/index_management/public/sections/index_list/components/index_actions_context_menu/index_actions_context_menu.container.js b/x-pack/plugins/index_management/public/sections/index_list/components/index_actions_context_menu/index_actions_context_menu.container.js
index bbf6a5d4a9cea..458c861dbfe05 100644
--- a/x-pack/plugins/index_management/public/sections/index_list/components/index_actions_context_menu/index_actions_context_menu.container.js
+++ b/x-pack/plugins/index_management/public/sections/index_list/components/index_actions_context_menu/index_actions_context_menu.container.js
@@ -15,11 +15,13 @@ import {
openIndices,
editIndexSettings,
refreshIndices,
- openDetailPanel
+ openDetailPanel,
+ performExtensionAction
} from '../../../../store/actions';
import {
- getIndexStatusByIndexName
+ getIndexStatusByIndexName,
+ getIndicesByName
} from '../../../../store/selectors';
const mapStateToProps = (state, ownProps) => {
@@ -29,7 +31,8 @@ const mapStateToProps = (state, ownProps) => {
indexStatusByName[indexName] = getIndexStatusByIndexName(state, indexName);
});
return {
- indexStatusByName
+ indexStatusByName,
+ indices: getIndicesByName(state, indexNames)
};
};
@@ -73,6 +76,9 @@ const mapDispatchToProps = (dispatch, { indexNames }) => {
},
deleteIndices: () => {
dispatch(deleteIndices({ indexNames }));
+ },
+ performExtensionAction: (requestMethod, successMessage) => {
+ dispatch(performExtensionAction({ requestMethod, successMessage, indexNames }));
}
};
};
diff --git a/x-pack/plugins/index_management/public/sections/index_list/components/index_actions_context_menu/index_actions_context_menu.js b/x-pack/plugins/index_management/public/sections/index_list/components/index_actions_context_menu/index_actions_context_menu.js
index 7c5339b53f75f..855c6ee7fe302 100644
--- a/x-pack/plugins/index_management/public/sections/index_list/components/index_actions_context_menu/index_actions_context_menu.js
+++ b/x-pack/plugins/index_management/public/sections/index_list/components/index_actions_context_menu/index_actions_context_menu.js
@@ -22,6 +22,7 @@ import {
} from '@elastic/eui';
import { flattenPanelTree } from '../../../../lib/flatten_panel_tree';
import { INDEX_OPEN } from '../../../../../common/constants';
+import { getActionExtensions } from '../../../../index_management_extensions';
class IndexActionsContextMenuUi extends Component {
constructor(props) {
@@ -46,6 +47,8 @@ class IndexActionsContextMenuUi extends Component {
detailPanel,
indexNames,
indexStatusByName,
+ performExtensionAction,
+ indices,
intl
} = this.props;
const allOpen = all(indexNames, indexName => {
@@ -174,6 +177,22 @@ class IndexActionsContextMenuUi extends Component {
this.openDeleteConfirmationModal();
}
});
+ getActionExtensions().forEach((actionExtension) => {
+ const actionExtensionDefinition = actionExtension(indices);
+ if (actionExtensionDefinition) {
+ const { buttonLabel, requestMethod, successMessage } = actionExtensionDefinition;
+ items.push({
+ name: buttonLabel,
+ icon: ,
+ onClick: () => {
+ this.closePopoverAndExecute(() => performExtensionAction(requestMethod, successMessage));
+ }
+ }
+
+ );
+ }
+ performExtensionAction;
+ });
items.forEach(item => {
item['data-test-subj'] = 'indexTableContextMenuButton';
});
diff --git a/x-pack/plugins/index_management/public/services/api.js b/x-pack/plugins/index_management/public/services/api.js
index fdbf800ce180c..ec74e309847a0 100644
--- a/x-pack/plugins/index_management/public/services/api.js
+++ b/x-pack/plugins/index_management/public/services/api.js
@@ -9,6 +9,9 @@ let httpClient;
export const setHttpClient = (client) => {
httpClient = client;
};
+export const getHttpClient = () => {
+ return httpClient;
+};
const apiPrefix = chrome.addBasePath('/api/index_management');
export async function loadIndices() {
diff --git a/x-pack/plugins/index_management/public/store/actions/extension_action.js b/x-pack/plugins/index_management/public/store/actions/extension_action.js
new file mode 100644
index 0000000000000..98ed6170f1b14
--- /dev/null
+++ b/x-pack/plugins/index_management/public/store/actions/extension_action.js
@@ -0,0 +1,20 @@
+/*
+ * 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 { reloadIndices } from '../actions';
+import { toastNotifications } from 'ui/notify';
+import { getHttpClient } from '../../services/api';
+
+export const performExtensionAction = ({ requestMethod, indexNames, successMessage }) => async (dispatch) => {
+ try {
+ await requestMethod(indexNames, getHttpClient());
+ } catch (error) {
+ toastNotifications.addDanger(error.data.message);
+ return;
+ }
+ dispatch(reloadIndices(indexNames));
+ toastNotifications.addSuccess(successMessage);
+};
diff --git a/x-pack/plugins/index_management/public/store/actions/index.js b/x-pack/plugins/index_management/public/store/actions/index.js
index 86c6280e12bbf..a50854015adea 100644
--- a/x-pack/plugins/index_management/public/store/actions/index.js
+++ b/x-pack/plugins/index_management/public/store/actions/index.js
@@ -19,4 +19,5 @@ export * from './table_state';
export * from './edit_index_settings';
export * from './update_index_settings';
export * from './detail_panel';
+export * from './extension_action';
diff --git a/x-pack/plugins/index_management/public/store/selectors/index.js b/x-pack/plugins/index_management/public/store/selectors/index.js
index 19a02908992e2..77019819fd5af 100644
--- a/x-pack/plugins/index_management/public/store/selectors/index.js
+++ b/x-pack/plugins/index_management/public/store/selectors/index.js
@@ -3,7 +3,6 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-
import { Pager } from '@elastic/eui';
import { createSelector } from 'reselect';
@@ -16,6 +15,11 @@ export const getDetailPanelType = (state) => state.detailPanel.panelType;
export const isDetailPanelOpen = (state) => !!getDetailPanelType(state);
export const getDetailPanelIndexName = (state) => state.detailPanel.indexName;
export const getIndices = (state) => state.indices.byId;
+export const getIndicesByName = (state, indexNames) => {
+ const indices = getIndices(state);
+ console.log(indices);
+ return indexNames.map((indexName) => indices[indexName]);
+};
export const getIndexByIndexName = (state, name) => getIndices(state)[name];
export const getFilteredIds = (state) => state.indices.filteredIds;
export const getRowStatuses = (state) => state.rowStatus;
From 88b0c7f34a65366fe18d4fc5224af0ee0ff2482a Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Fri, 2 Nov 2018 14:23:33 -0400
Subject: [PATCH 083/102] first pass at index lifecycle banner
---
.../components/index_lifecycle_banner.js | 27 +++++++++++++++++++
.../public/index.js | 1 +
.../public/register_index_lifecycle_banner.js | 20 ++++++++++++++
.../public/index_management_extensions.js | 7 +++++
.../components/index_table/index_table.js | 7 ++++-
5 files changed, 61 insertions(+), 1 deletion(-)
create mode 100644 x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_banner.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_banner.js
diff --git a/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_banner.js b/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_banner.js
new file mode 100644
index 0000000000000..c492d56571c7b
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_banner.js
@@ -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 {
+ EuiCallOut,
+ EuiText
+} from '@elastic/eui';
+
+export const IndexLifecycleBanner = (props) => {
+ const numberOfErroredIndices = props.indices.length;
+ return (
+
+
+ { numberOfErroredIndices } ind{numberOfErroredIndices > 1 ? 'icies have ' : 'ex has ' } index lifecycle errors.
+
+
+ );
+};
\ No newline at end of file
diff --git a/x-pack/plugins/index_lifecycle_management/public/index.js b/x-pack/plugins/index_lifecycle_management/public/index.js
index 867ee0e3ef913..272904e39a8a2 100644
--- a/x-pack/plugins/index_lifecycle_management/public/index.js
+++ b/x-pack/plugins/index_lifecycle_management/public/index.js
@@ -8,3 +8,4 @@ import './register_management_section';
import './register_routes';
import './register_index_lifecycle_summary';
import './register_index_lifecycle_actions';
+import './register_index_lifecycle_banner';
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_banner.js b/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_banner.js
new file mode 100644
index 0000000000000..0d9b37f516b3e
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_banner.js
@@ -0,0 +1,20 @@
+/*
+ * 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 { addBannerExtension } from '../../index_management/public/index_management_extensions';
+import { IndexLifecycleBanner } from './components/index_lifecycle_banner';
+addBannerExtension((indices) =>{
+ if (!indices.length) {
+ return null;
+ }
+ const indicesWithLifecycleErrors = indices.filter((index) => {
+ return index.ilm && index.ilm.failed_step;
+ });
+ if (!indicesWithLifecycleErrors.length) {
+ return null;
+ }
+ return ;
+});
\ No newline at end of file
diff --git a/x-pack/plugins/index_management/public/index_management_extensions.js b/x-pack/plugins/index_management/public/index_management_extensions.js
index 192b75d4f4446..25ebb5eb0445a 100644
--- a/x-pack/plugins/index_management/public/index_management_extensions.js
+++ b/x-pack/plugins/index_management/public/index_management_extensions.js
@@ -18,5 +18,12 @@ export const addActionExtension = (actionExtension)=> {
export const getActionExtensions = () => {
return actionExtensions;
};
+const bannerExtensions = [];
+export const addBannerExtension = (actionExtension)=> {
+ bannerExtensions.push(actionExtension);
+};
+export const getBannerExtensions = () => {
+ return bannerExtensions;
+};
diff --git a/x-pack/plugins/index_management/public/sections/index_list/components/index_table/index_table.js b/x-pack/plugins/index_management/public/sections/index_list/components/index_table/index_table.js
index df501ef98ff32..e61489bbd1d0e 100644
--- a/x-pack/plugins/index_management/public/sections/index_list/components/index_table/index_table.js
+++ b/x-pack/plugins/index_management/public/sections/index_list/components/index_table/index_table.js
@@ -39,6 +39,7 @@ import {
} from '@elastic/eui';
import { IndexActionsContextMenu } from '../../components';
+import { getBannerExtensions } from '../../../../index_management_extensions';
const HEADERS = {
name: i18n.translate('xpack.idxMgmt.indexTable.headers.nameHeader', {
@@ -196,7 +197,10 @@ export class IndexTableUi extends Component {
);
});
}
-
+ renderBanners() {
+ const { indices = [] } = this.props;
+ return getBannerExtensions().map(bannerExtension => bannerExtension(indices));
+ }
buildRows() {
const { indices = [], detailPanelIndexName } = this.props;
return indices.map(index => {
@@ -292,6 +296,7 @@ export class IndexTableUi extends Component {
+ { this.renderBanners()}
{atLeastOneItemSelected ? (
From 94ef3e7296f00ecf4a54ca8ee1e8f8708ed58171 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Fri, 7 Sep 2018 09:53:03 -0400
Subject: [PATCH 084/102] i18n work
---
.../public/components/learn_more_link.js | 12 +++++---
.../components/policy_table/confirm_delete.js | 30 ++++++++++++++-----
2 files changed, 31 insertions(+), 11 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/components/learn_more_link.js b/x-pack/plugins/index_lifecycle_management/public/components/learn_more_link.js
index 17f6e5e2d1661..25ebeac229729 100644
--- a/x-pack/plugins/index_lifecycle_management/public/components/learn_more_link.js
+++ b/x-pack/plugins/index_lifecycle_management/public/components/learn_more_link.js
@@ -7,11 +7,11 @@
import React from 'react';
import { EuiLink } from '@elastic/eui';
import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links';
-
+import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
const esBase = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`;
-export class LearnMoreLink extends React.PureComponent {
+export class LearnMoreLinkUi extends React.PureComponent {
render() {
const { href, docPath } = this.props;
let url;
@@ -22,9 +22,13 @@ export class LearnMoreLink extends React.PureComponent {
}
return (
- Learn more
+
);
}
-}
\ No newline at end of file
+}
+export const LearnMoreLink = injectI18n(LearnMoreLinkUi);
\ No newline at end of file
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/confirm_delete.js b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/confirm_delete.js
index d3ad96e8b1b8c..596ccb6645ea1 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/confirm_delete.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/policy_table/components/policy_table/confirm_delete.js
@@ -5,27 +5,39 @@
*/
import React, { Component } from 'react';
+import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
import { EuiOverlayMask, EuiConfirmModal } from '@elastic/eui';
import { toastNotifications } from 'ui/notify';
import { deletePolicy } from '../../../../api';
-export class ConfirmDelete extends Component {
+export class ConfirmDeleteUi extends Component {
deletePolicy = async () => {
- const { policyToDelete, callback } = this.props;
+ const { intl, policyToDelete, callback } = this.props;
const policyName = policyToDelete.name;
try {
await deletePolicy(policyName);
- toastNotifications.addSuccess(`Deleted policy ${policyName}`);
+ const message = intl.formatMessage({
+ id: 'xpack.indexLifecycleMgmt.confirmDelete.successMessage',
+ defaultMessage: 'Deleted policy {policyName}',
+ }, { policyName });
+ toastNotifications.addSuccess(message);
} catch (e) {
- toastNotifications.addDanger(`Error deleting policy ${policyName}`);
+ const message = intl.formatMessage({
+ id: 'xpack.indexLifecycleMgmt.confirmDelete.errorMessage',
+ defaultMessage: 'Error deleting policy}{policyName}',
+ }, { policyName });
+ toastNotifications.addDanger(message);
}
if (callback) {
callback();
}
};
render() {
- const { policyToDelete, onCancel } = this.props;
- const title = `Delete policy '${policyToDelete.name}'`;
+ const { intl, policyToDelete, onCancel } = this.props;
+ const title = intl.formatMessage({
+ id: 'xpack.indexLifecycleMgmt.confirmDelete.title',
+ defaultMessage: 'Delete {name}',
+ }, { name: policyToDelete.name });
return (
-
This operation cannot be undone.
+
);
}
}
+export const ConfirmDelete = injectI18n(ConfirmDeleteUi);
From c902b7018c4a42a2994dd78e345bc5c4123a8d1b Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Fri, 7 Sep 2018 12:54:25 -0400
Subject: [PATCH 085/102] more i18n
---
.../node_attrs_details/node_attrs_details.js | 42 +++++++++++++++----
1 file changed, 33 insertions(+), 9 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/node_attrs_details.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/node_attrs_details.js
index 7cb2977e706ab..e55a6df0e9013 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/node_attrs_details.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/node_attrs_details/node_attrs_details.js
@@ -18,8 +18,10 @@ import {
EuiCallOut,
EuiPortal,
} from '@elastic/eui';
+import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
-export class NodeAttrsDetails extends PureComponent {
+
+export class NodeAttrsDetailsUi extends PureComponent {
static propTypes = {
fetchNodeDetails: PropTypes.func.isRequired,
close: PropTypes.func.isRequired,
@@ -34,14 +36,20 @@ export class NodeAttrsDetails extends PureComponent {
}
render() {
- const { selectedNodeAttrs, allocationRules, details, close } = this.props;
+ const { selectedNodeAttrs, allocationRules, details, close, intl } = this.props;
return (
- Nodes that contain the attribute: `{selectedNodeAttrs}`
+
+
+
{allocationRules ? (
@@ -51,8 +59,10 @@ export class NodeAttrsDetails extends PureComponent {
title="Heads up"
color="warning"
>
- Be aware that this index template has existing allocation rules
- which will affect the list of nodes these indices can be allocated to.
+
@@ -60,9 +70,18 @@ export class NodeAttrsDetails extends PureComponent {
- Close
+
@@ -78,3 +100,5 @@ export class NodeAttrsDetails extends PureComponent {
);
}
}
+export const NodeAttrsDetails = injectI18n(NodeAttrsDetailsUi);
+
From b5e2f04a1c9b631df429f9b76d5a1ef385157bd3 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 5 Nov 2018 13:19:54 -0500
Subject: [PATCH 086/102] fixing issue with node attributes
---
.../public/store/selectors/index_template.js | 7 ++++---
.../public/store/selectors/policies.js | 7 +++++--
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/index_template.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/index_template.js
index 339d5380613ff..0ba81b4595296 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/index_template.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/index_template.js
@@ -124,7 +124,7 @@ export const getExistingAllocationRules = state => {
const hasJSONChanged = (json1, json2) => JSON.stringify(json1) !== JSON.stringify(json2);
export const getTemplateDiff = state => {
const originalFullIndexTemplate = getFullSelectedIndexTemplate(state) || { settings: {} };
- const attributeName = getSelectedNodeAttrs(state);
+ const attributeNameAndValue = getSelectedNodeAttrs(state);
const baseNewFullIndexTemplate = {
settings: {
index: {
@@ -136,11 +136,12 @@ export const getTemplateDiff = state => {
}
}
};
- if (attributeName) {
+ if (attributeNameAndValue) {
+ const [ name, value ] = attributeNameAndValue.split[':'];
baseNewFullIndexTemplate.routing = {
allocation: {
include: {
- sattr_name: attributeName,
+ [name]: value,
}
}
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
index d41ef602b8430..5f4734626cc93 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
@@ -179,7 +179,9 @@ export const phaseFromES = (phase, phaseName, defaultPolicy) => {
if (actions.allocate) {
const allocate = actions.allocate;
if (allocate.require) {
- policy[PHASE_NODE_ATTRS] = allocate.require._name;
+ Object.entries(allocate.require).forEach((entry) => {
+ policy[PHASE_NODE_ATTRS] = entry.join(':');
+ });
}
}
@@ -248,11 +250,12 @@ export const phaseToES = (state, phase) => {
}
}
if (phase[PHASE_NODE_ATTRS]) {
+ const [ name, value, ] = phase[PHASE_NODE_ATTRS].split(':');
esPhase.actions.allocate = {
include: {}, // TODO: this seems to be a constant, confirm?
exclude: {}, // TODO: this seems to be a constant, confirm?
require: {
- _name: phase[PHASE_NODE_ATTRS]
+ [name]: value
}
};
if (isNumber(phase[PHASE_REPLICA_COUNT])) {
From 861a0e856935bbbf1f878931fa0591b669e37283 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 5 Nov 2018 13:21:31 -0500
Subject: [PATCH 087/102] removing console.log statements
---
.../index_list/components/detail_panel/summary/summary.js | 1 -
x-pack/plugins/index_management/public/store/selectors/index.js | 1 -
2 files changed, 2 deletions(-)
diff --git a/x-pack/plugins/index_management/public/sections/index_list/components/detail_panel/summary/summary.js b/x-pack/plugins/index_management/public/sections/index_list/components/detail_panel/summary/summary.js
index 44b5ca4c24930..9a33de20f9d6d 100644
--- a/x-pack/plugins/index_management/public/sections/index_list/components/detail_panel/summary/summary.js
+++ b/x-pack/plugins/index_management/public/sections/index_list/components/detail_panel/summary/summary.js
@@ -53,7 +53,6 @@ export class Summary extends React.PureComponent {
getAdditionalContent() {
const { index } = this.props;
const extensions = getSummaryExtensions();
- console.log(extensions);
return extensions.map((summaryExtension) => {
return (
diff --git a/x-pack/plugins/index_management/public/store/selectors/index.js b/x-pack/plugins/index_management/public/store/selectors/index.js
index 77019819fd5af..ec08aa69d1f11 100644
--- a/x-pack/plugins/index_management/public/store/selectors/index.js
+++ b/x-pack/plugins/index_management/public/store/selectors/index.js
@@ -17,7 +17,6 @@ export const getDetailPanelIndexName = (state) => state.detailPanel.indexName;
export const getIndices = (state) => state.indices.byId;
export const getIndicesByName = (state, indexNames) => {
const indices = getIndices(state);
- console.log(indices);
return indexNames.map((indexName) => indices[indexName]);
};
export const getIndexByIndexName = (state, name) => getIndices(state)[name];
From f1fc1f7460cce25a9d242aa1488e978302a2cbe2 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 5 Nov 2018 13:48:18 -0500
Subject: [PATCH 088/102] fixing issue with deserializing number_of_shards for
edit policy
---
.../public/store/selectors/policies.js | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
index 5f4734626cc93..be50ad382c87a 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/policies.js
@@ -182,6 +182,10 @@ export const phaseFromES = (phase, phaseName, defaultPolicy) => {
Object.entries(allocate.require).forEach((entry) => {
policy[PHASE_NODE_ATTRS] = entry.join(':');
});
+ // checking for null or undefined here
+ if (allocate.number_of_replicas != null) {
+ policy[PHASE_REPLICA_COUNT] = allocate.number_of_replicas;
+ }
}
}
@@ -194,11 +198,6 @@ export const phaseFromES = (phase, phaseName, defaultPolicy) => {
if (actions.shrink) {
policy[PHASE_PRIMARY_SHARD_COUNT] = actions.shrink.number_of_shards;
}
-
- if (actions.replicas) {
- const replicas = actions.replicas;
- policy[PHASE_REPLICA_COUNT] = replicas.number_of_replicas;
- }
}
return policy;
};
From 7bd290038cb55d0eaed2fcf2b5310f6a3524c708 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 5 Nov 2018 13:52:38 -0500
Subject: [PATCH 089/102] defaulting shrink to false and fixing ui spacing
issue
---
.../sections/edit_policy/components/warm_phase/warm_phase.js | 1 +
.../public/store/defaults/warm_phase.js | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
index 4320e043489f0..fc80aad807281 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
@@ -255,6 +255,7 @@ export class WarmPhase extends PureComponent {
/>
{phaseData[PHASE_SHRINK_ENABLED] ? (
+
Date: Mon, 5 Nov 2018 14:00:17 -0500
Subject: [PATCH 090/102] removing hot phase shard count from warm phase
---
.../warm_phase/warm_phase.container.js | 4 ---
.../components/warm_phase/warm_phase.js | 34 -------------------
2 files changed, 38 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js
index b6d1c579de58f..c21cc9e7bfbee 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.container.js
@@ -12,8 +12,6 @@ import { WarmPhase as PresentationComponent } from './warm_phase';
import {
getNodeOptions,
getPhase,
- getSelectedReplicaCount,
- getSelectedPrimaryShardCount
} from '../../../../store/selectors';
import { setPhaseData, fetchNodes } from '../../../../store/actions';
import { PHASE_WARM, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../store/constants';
@@ -21,8 +19,6 @@ import { PHASE_WARM, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../store
export const WarmPhase = connect(
state => ({
phaseData: getPhase(state, PHASE_WARM),
- hotPhaseReplicaCount: Number(getSelectedReplicaCount(state)),
- hotPhasePrimaryShardCount: Number(getSelectedPrimaryShardCount(state)),
hotPhaseRolloverEnabled: getPhase(state, PHASE_HOT)[PHASE_ROLLOVER_ENABLED],
nodeOptions: getNodeOptions(state)
}),
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
index fc80aad807281..1723ff9d0deca 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
@@ -59,10 +59,6 @@ export class WarmPhase extends PureComponent {
[PHASE_ROLLOVER_MINIMUM_AGE]: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired,
[PHASE_ROLLOVER_MINIMUM_AGE_UNITS]: PropTypes.string.isRequired,
}).isRequired,
-
- hotPhaseReplicaCount: PropTypes.number.isRequired,
- hotPhasePrimaryShardCount: PropTypes.number.isRequired,
-
nodeOptions: PropTypes.array.isRequired,
};
@@ -74,10 +70,7 @@ export class WarmPhase extends PureComponent {
const {
setPhaseData,
showNodeDetailsFlyout,
-
phaseData,
- hotPhaseReplicaCount,
- hotPhasePrimaryShardCount,
nodeOptions,
errors,
isShowingErrors,
@@ -217,18 +210,6 @@ export class WarmPhase extends PureComponent {
/>
-
-
- {
- await setPhaseData(PHASE_REPLICA_COUNT, hotPhaseReplicaCount);
- }}
- >
- Set to same as hot phase
-
-
-
@@ -273,21 +254,6 @@ export class WarmPhase extends PureComponent {
/>
-
-
- {
- await setPhaseData(
- PHASE_PRIMARY_SHARD_COUNT,
- hotPhasePrimaryShardCount
- );
- }}
- >
- Set to same as hot phase
-
-
-
From 008d37c6374d802543811bffdbbc086b20681d50 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 5 Nov 2018 17:08:38 -0500
Subject: [PATCH 091/102] scrolling to first error when user submits form for
edit policy
---
.../public/lib/find_errors.js | 23 ++++++++++------
.../components/cold_phase/cold_phase.js | 4 +++
.../components/delete_phase/delete_phase.js | 2 ++
.../components/hot_phase/hot_phase.js | 7 ++++-
.../components/warm_phase/warm_phase.js | 6 +++++
.../edit_policy/edit_policy.container.js | 26 ++++++++++++-------
.../sections/edit_policy/edit_policy.js | 19 +++++++++-----
7 files changed, 61 insertions(+), 26 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/find_errors.js b/x-pack/plugins/index_lifecycle_management/public/lib/find_errors.js
index 39d260b05301e..6a95326ee85c9 100644
--- a/x-pack/plugins/index_lifecycle_management/public/lib/find_errors.js
+++ b/x-pack/plugins/index_lifecycle_management/public/lib/find_errors.js
@@ -4,19 +4,26 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export const hasErrors = (object, keysToIgnore = []) => {
- let errors = false;
- for (const [key, value] of Object.entries(object)) {
- if (keysToIgnore.includes(key)) continue;
+export const findFirstError = (object, topLevel = true) => {
+ console.log("ERRORS", object);
+
+ let firstError;
+ const keys = topLevel ? [ 'policyName', 'hot', 'warm', 'cold', 'delete'] : Object.keys(object);
+ for (const key of keys) {
+ const value = object[key];
if (Array.isArray(value) && value.length > 0) {
- errors = true;
+ firstError = key;
+ console.log(`Found error ${firstError}`);
break;
} else if (value) {
- errors = hasErrors(value, keysToIgnore);
- if (errors) {
+ firstError = findFirstError(value, false);
+ if (firstError) {
+ firstError = `${key}.${firstError}`;
+ console.log(`Found error ${firstError}`);
break;
}
}
}
- return errors;
+ console.log(`Returning ${firstError}`);
+ return firstError;
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js
index 3e24bc18da1be..6ee756c142b61 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js
@@ -22,6 +22,7 @@ import {
EuiButton,
} from '@elastic/eui';
import {
+ PHASE_COLD,
PHASE_ENABLED,
PHASE_ROLLOVER_ALIAS,
PHASE_ROLLOVER_MINIMUM_AGE,
@@ -118,6 +119,7 @@ export class ColdPhase extends PureComponent {
@@ -173,6 +177,7 @@ export class HotPhase extends PureComponent {
({
- errors: validateLifecycle(state),
- selectedPolicy: getSelectedPolicy(state),
- affectedIndexTemplates: getAffectedIndexTemplates(state),
- saveAsNewPolicy: getSaveAsNewPolicy(state),
- lifecycle: getLifecycle(state),
- policies: getPolicies(state),
- isPolicyListLoaded: isPolicyListLoaded(state),
- isNewPolicy: getIsNewPolicy(state),
- }),
+ state => {
+ const errors = validateLifecycle(state);
+ const firstError = findFirstError(errors);
+ return {
+ firstError,
+ errors,
+ selectedPolicy: getSelectedPolicy(state),
+ affectedIndexTemplates: getAffectedIndexTemplates(state),
+ saveAsNewPolicy: getSaveAsNewPolicy(state),
+ lifecycle: getLifecycle(state),
+ policies: getPolicies(state),
+ isPolicyListLoaded: isPolicyListLoaded(state),
+ isNewPolicy: getIsNewPolicy(state),
+ };
+ },
{
setSelectedPolicy,
setSelectedPolicyName,
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
index 4686efb39928d..9715953c53d3b 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
@@ -34,7 +34,7 @@ import {
PHASE_WARM,
STRUCTURE_POLICY_NAME,
} from '../../store/constants';
-import { hasErrors } from '../../lib/find_errors';
+import { findFirstError } from '../../lib/find_errors';
import { NodeAttrsDetails } from './components/node_attrs_details';
import { ErrableFormRow } from './form_errors';
@@ -87,13 +87,17 @@ export class EditPolicy extends Component {
submit = async () => {
this.setState({ isShowingErrors: true });
const {
- errors,
saveLifecyclePolicy,
lifecycle,
saveAsNewPolicy,
+ firstError
} = this.props;
- if (hasErrors(errors)) {
+ if (firstError) {
toastNotifications.addDanger('Please the fix errors on the page');
+ const element = document.getElementById(`${firstError}-row`);
+ if (element) {
+ element.scrollIntoView();
+ }
} else {
const success = await saveLifecyclePolicy(lifecycle, saveAsNewPolicy);
if (success) {
@@ -176,6 +180,7 @@ export class EditPolicy extends Component {
{saveAsNewPolicy || !policyName ? (
From 45d4e8c51d8569351a6c2548a7ee73429e066747 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Tue, 6 Nov 2018 09:22:52 -0500
Subject: [PATCH 092/102] disabling UI for index management when enabled is
false in kibana.yml
---
x-pack/plugins/index_management/index.js | 8 ++++-
.../public/register_management_section.js | 17 ++++++-----
.../public/register_routes.js | 30 ++++++++++---------
3 files changed, 33 insertions(+), 22 deletions(-)
diff --git a/x-pack/plugins/index_management/index.js b/x-pack/plugins/index_management/index.js
index c48eaa6ba15ca..6e29b91882d48 100644
--- a/x-pack/plugins/index_management/index.js
+++ b/x-pack/plugins/index_management/index.js
@@ -21,7 +21,13 @@ export function indexManagement(kibana) {
styleSheetPaths: `${__dirname}/public/index.scss`,
managementSections: [
'plugins/index_management',
- ]
+ ],
+ injectDefaultVars(server) {
+ const config = server.config();
+ return {
+ indexManagementUiEnabled: config.get(`${PLUGIN.ID}.enabled`)
+ };
+ },
},
init: function (server) {
server.expose('addIndexManagementDataEnricher', addIndexManagementDataEnricher);
diff --git a/x-pack/plugins/index_management/public/register_management_section.js b/x-pack/plugins/index_management/public/register_management_section.js
index 78dec3515a899..3f084da770e1d 100644
--- a/x-pack/plugins/index_management/public/register_management_section.js
+++ b/x-pack/plugins/index_management/public/register_management_section.js
@@ -7,12 +7,15 @@
import { management } from 'ui/management';
import { i18n } from '@kbn/i18n';
import { BASE_PATH } from '../common/constants';
+import chrome from 'ui/chrome';
+if (chrome.getInjected('indexManagementUiEnabled')) {
+ const esSection = management.getSection('elasticsearch');
+ esSection.register('index_management', {
+ visible: true,
+ display: i18n.translate('xpack.idxMgmt.appTitle', { defaultMessage: 'Index Management' }),
+ order: 1,
+ url: `#${BASE_PATH}home`
+ });
+}
-const esSection = management.getSection('elasticsearch');
-esSection.register('index_management', {
- visible: true,
- display: i18n.translate('xpack.idxMgmt.appTitle', { defaultMessage: 'Index Management' }),
- order: 1,
- url: `#${BASE_PATH}home`
-});
diff --git a/x-pack/plugins/index_management/public/register_routes.js b/x-pack/plugins/index_management/public/register_routes.js
index 02666e81a0b5c..acae726940b04 100644
--- a/x-pack/plugins/index_management/public/register_routes.js
+++ b/x-pack/plugins/index_management/public/register_routes.js
@@ -19,6 +19,7 @@ import routes from 'ui/routes';
import template from './main.html';
import { manageAngularLifecycle } from './lib/manage_angular_lifecycle';
import { indexManagementStore } from './store';
+import chrome from 'ui/chrome';
const renderReact = async (elem) => {
render(
@@ -32,21 +33,22 @@ const renderReact = async (elem) => {
elem
);
};
-
-routes.when(`${BASE_PATH}:view?/:id?`, {
- template: template,
- controllerAs: 'indexManagement',
- controller: class IndexManagementController {
- constructor($scope, $route, $http) {
+if (chrome.getInjected('indexManagementUiEnabled')) {
+ routes.when(`${BASE_PATH}:view?/:id?`, {
+ template: template,
+ controllerAs: 'indexManagement',
+ controller: class IndexManagementController {
+ constructor($scope, $route, $http) {
// NOTE: We depend upon Angular's $http service because it's decorated with interceptors,
// e.g. to check license status per request.
- setHttpClient($http);
+ setHttpClient($http);
- $scope.$$postDigest(() => {
- const elem = document.getElementById('indexManagementReactRoot');
- renderReact(elem);
- manageAngularLifecycle($scope, $route, elem);
- });
+ $scope.$$postDigest(() => {
+ const elem = document.getElementById('indexManagementReactRoot');
+ renderReact(elem);
+ manageAngularLifecycle($scope, $route, elem);
+ });
+ }
}
- }
-});
+ });
+}
From e16aa554340cd68b64dae44ee6ba76f726acceaf Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Tue, 6 Nov 2018 09:35:19 -0500
Subject: [PATCH 093/102] disabling index lifecycle management when enabled is
false in kibana.yml
---
.../index_lifecycle_management/index.js | 6 +++
.../public/index.js | 4 +-
.../index.js | 12 ++++++
.../register_index_lifecycle_actions.js | 4 +-
.../register_index_lifecycle_banner.js | 4 +-
.../register_index_lifecycle_summary.js | 4 +-
.../public/register_management_section.js | 18 ++++----
.../public/register_routes.js | 43 ++++++++++---------
8 files changed, 58 insertions(+), 37 deletions(-)
create mode 100644 x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/index.js
rename x-pack/plugins/index_lifecycle_management/public/{ => register_index_management_extensions}/register_index_lifecycle_actions.js (87%)
rename x-pack/plugins/index_lifecycle_management/public/{ => register_index_management_extensions}/register_index_lifecycle_banner.js (77%)
rename x-pack/plugins/index_lifecycle_management/public/{ => register_index_management_extensions}/register_index_lifecycle_summary.js (66%)
diff --git a/x-pack/plugins/index_lifecycle_management/index.js b/x-pack/plugins/index_lifecycle_management/index.js
index 4c666fffde158..ce483d9218864 100644
--- a/x-pack/plugins/index_lifecycle_management/index.js
+++ b/x-pack/plugins/index_lifecycle_management/index.js
@@ -20,6 +20,12 @@ export function indexLifecycleManagement(kibana) {
require: ['kibana', 'elasticsearch', 'xpack_main', 'index_management'],
uiExports: {
managementSections: ['plugins/index_lifecycle_management'],
+ injectDefaultVars(server) {
+ const config = server.config();
+ return {
+ indexLifecycleManagementUiEnabled: config.get(`${PLUGIN.ID}.enabled`)
+ };
+ },
},
init: function (server) {
registerLicenseChecker(server);
diff --git a/x-pack/plugins/index_lifecycle_management/public/index.js b/x-pack/plugins/index_lifecycle_management/public/index.js
index 272904e39a8a2..3747d4e89a7b1 100644
--- a/x-pack/plugins/index_lifecycle_management/public/index.js
+++ b/x-pack/plugins/index_lifecycle_management/public/index.js
@@ -6,6 +6,4 @@
import './register_management_section';
import './register_routes';
-import './register_index_lifecycle_summary';
-import './register_index_lifecycle_actions';
-import './register_index_lifecycle_banner';
+import './register_index_management_extensions';
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/index.js b/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/index.js
new file mode 100644
index 0000000000000..706894c14eacc
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/index.js
@@ -0,0 +1,12 @@
+/*
+ * 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 chrome from 'ui/chrome';
+if (chrome.getInjected('indexLifecycleManagementUiEnabled')) {
+ require('./register_index_lifecycle_actions');
+ require('./register_index_lifecycle_banner');
+ require('./register_index_lifecycle_summary');
+}
\ No newline at end of file
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_actions.js b/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_actions.js
similarity index 87%
rename from x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_actions.js
rename to x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_actions.js
index f37e06f8a8c4e..9e265d82009c8 100644
--- a/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_actions.js
+++ b/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_actions.js
@@ -6,8 +6,8 @@
import { every } from 'lodash';
import { i18n } from '@kbn/i18n';
-import { addActionExtension } from '../../index_management/public/index_management_extensions';
-import { retryLifecycleForIndex } from './api';
+import { addActionExtension } from '../../../index_management/public/index_management_extensions';
+import { retryLifecycleForIndex } from '../api';
addActionExtension((indices) => {
const allHaveErrors = every(indices, (index) => {
return (index.ilm && index.ilm.failed_step);
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_banner.js b/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_banner.js
similarity index 77%
rename from x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_banner.js
rename to x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_banner.js
index 0d9b37f516b3e..0fa78985fc407 100644
--- a/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_banner.js
+++ b/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_banner.js
@@ -4,8 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
-import { addBannerExtension } from '../../index_management/public/index_management_extensions';
-import { IndexLifecycleBanner } from './components/index_lifecycle_banner';
+import { addBannerExtension } from '../../../index_management/public/index_management_extensions';
+import { IndexLifecycleBanner } from '../components/index_lifecycle_banner';
addBannerExtension((indices) =>{
if (!indices.length) {
return null;
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_summary.js b/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_summary.js
similarity index 66%
rename from x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_summary.js
rename to x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_summary.js
index cd5a262b1635a..e1a74f0dd6991 100644
--- a/x-pack/plugins/index_lifecycle_management/public/register_index_lifecycle_summary.js
+++ b/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_summary.js
@@ -5,8 +5,8 @@
*/
import React from 'react';
-import { addSummaryExtension } from '../../index_management/public/index_management_extensions';
-import { IndexLifecycleSummary } from './components/index_lifecycle_summary';
+import { addSummaryExtension } from '../../../index_management/public/index_management_extensions';
+import { IndexLifecycleSummary } from '../components/index_lifecycle_summary';
addSummaryExtension((index) => {
return ;
});
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_management_section.js b/x-pack/plugins/index_lifecycle_management/public/register_management_section.js
index 461f94c573c5f..ed6ecfd756028 100644
--- a/x-pack/plugins/index_lifecycle_management/public/register_management_section.js
+++ b/x-pack/plugins/index_lifecycle_management/public/register_management_section.js
@@ -6,12 +6,14 @@
import { management } from 'ui/management';
import { BASE_PATH } from '../common/constants';
-
-const esSection = management.getSection('elasticsearch');
-esSection.register('index_lifecycle_management', {
- visible: true,
- display: 'Index Lifecycle Management',
- order: 1,
- url: `#${BASE_PATH}policies`
-});
+import chrome from 'ui/chrome';
+if (chrome.getInjected('indexLifecycleManagementUiEnabled')) {
+ const esSection = management.getSection('elasticsearch');
+ esSection.register('index_lifecycle_management', {
+ visible: true,
+ display: 'Index Lifecycle Management',
+ order: 1,
+ url: `#${BASE_PATH}policies`
+ });
+}
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_routes.js b/x-pack/plugins/index_lifecycle_management/public/register_routes.js
index 6395abca92c3c..27a26b98f503b 100644
--- a/x-pack/plugins/index_lifecycle_management/public/register_routes.js
+++ b/x-pack/plugins/index_lifecycle_management/public/register_routes.js
@@ -19,6 +19,7 @@ import routes from 'ui/routes';
import template from './main.html';
import { manageAngularLifecycle } from './lib/manage_angular_lifecycle';
+import chrome from 'ui/chrome';
const renderReact = async (elem) => {
render(
@@ -30,24 +31,26 @@ const renderReact = async (elem) => {
elem
);
};
-
-routes.when(`${BASE_PATH}:view?/:action?/:id?`, {
- template: template,
- controllerAs: 'indexManagement',
- controller: class IndexManagementController {
- constructor($scope, $route, $http, kbnUrl, $rootScope) {
- setHttpClient($http);
- setUrlService({
- change(url) {
- kbnUrl.change(url);
- $rootScope.$digest();
- }
- });
- $scope.$$postDigest(() => {
- const elem = document.getElementById('indexLifecycleManagementReactRoot');
- renderReact(elem);
- manageAngularLifecycle($scope, $route, elem);
- });
+if (chrome.getInjected('indexLifecycleManagementUiEnabled')) {
+ routes.when(`${BASE_PATH}:view?/:action?/:id?`, {
+ template: template,
+ controllerAs: 'indexLifecycleManagement',
+ controller: class IndexLifecycleManagementController {
+ constructor($scope, $route, $http, kbnUrl, $rootScope) {
+ console.log("ILM");
+ setHttpClient($http);
+ setUrlService({
+ change(url) {
+ kbnUrl.change(url);
+ $rootScope.$digest();
+ }
+ });
+ $scope.$$postDigest(() => {
+ const elem = document.getElementById('indexLifecycleManagementReactRoot');
+ renderReact(elem);
+ manageAngularLifecycle($scope, $route, elem);
+ });
+ }
}
- }
-});
+ });
+}
From 71d4889ab9c0a7856b15d39055a42f0ddbf5a0d1 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 12 Nov 2018 07:40:03 -0500
Subject: [PATCH 094/102] extending index management filter to allow for
searching fields
---
.../index_list/components/index_table/index_table.js | 3 ---
.../index_management/public/services/filter_items.js | 8 ++++++--
.../index_management/public/store/selectors/index.js | 10 +++++++++-
3 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/x-pack/plugins/index_management/public/sections/index_list/components/index_table/index_table.js b/x-pack/plugins/index_management/public/sections/index_list/components/index_table/index_table.js
index e61489bbd1d0e..0f7e90ef7eee3 100644
--- a/x-pack/plugins/index_management/public/sections/index_list/components/index_table/index_table.js
+++ b/x-pack/plugins/index_management/public/sections/index_list/components/index_table/index_table.js
@@ -63,9 +63,6 @@ const HEADERS = {
size: i18n.translate('xpack.idxMgmt.indexTable.headers.storageSizeHeader', {
defaultMessage: 'Storage size',
}),
- primary_size: i18n.translate('xpack.idxMgmt.indexTable.headers.primaryStorageSizeHeader', {
- defaultMessage: 'Primary storage size',
- })
};
export class IndexTableUi extends Component {
diff --git a/x-pack/plugins/index_management/public/services/filter_items.js b/x-pack/plugins/index_management/public/services/filter_items.js
index 6d2e3dae57f46..3ec88bf600246 100644
--- a/x-pack/plugins/index_management/public/services/filter_items.js
+++ b/x-pack/plugins/index_management/public/services/filter_items.js
@@ -3,13 +3,17 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
+import { get } from 'lodash';
export const filterItems = (fields, filter = '', items = []) => {
- const lowerFilter = filter.toLowerCase();
+ const lowerFilter = filter.trim().toLowerCase();
return items.filter(item => {
const actualFields = fields || Object.keys(item);
const indexOfMatch = actualFields.findIndex(field => {
- const normalizedField = String(item[field]).toLowerCase();
+ console.log('GETTING', item, field, filter);
+ const normalizedField = String(get(item, field)).toLowerCase();
+ console.log('N', normalizedField);
+ console.log("MATCH?", normalizedField.includes(lowerFilter));
return normalizedField.includes(lowerFilter);
});
return indexOfMatch !== -1;
diff --git a/x-pack/plugins/index_management/public/store/selectors/index.js b/x-pack/plugins/index_management/public/store/selectors/index.js
index ec08aa69d1f11..fe0d1678c1b35 100644
--- a/x-pack/plugins/index_management/public/store/selectors/index.js
+++ b/x-pack/plugins/index_management/public/store/selectors/index.js
@@ -30,6 +30,7 @@ export const getIndexStatusByIndexName = (state, indexName) => {
const { status } = indices[indexName] || {};
return status;
};
+const defaultFilterFields = ['name', 'uuid'];
const getFilteredIndices = createSelector(
getIndices,
getRowStatuses,
@@ -39,7 +40,14 @@ const getFilteredIndices = createSelector(
const systemFilteredIndexes = tableState.showSystemIndices
? indexArray
: indexArray.filter(index => !(index.name + '').startsWith('.'));
- return filterItems(['name', 'uuid'], tableState.filter, systemFilteredIndexes);
+ let filter = tableState.filter;
+ let fields = defaultFilterFields;
+ if (filter.includes(':')) {
+ const splitFilter = filter.split(':');
+ fields = [ splitFilter[0]];
+ filter = splitFilter[1];
+ }
+ return filterItems(fields, filter, systemFilteredIndexes);
}
);
export const getTotalItems = createSelector(
From 013bf6a0f44b521c3ef14d64bddfc8f491c30100 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 12 Nov 2018 08:59:57 -0500
Subject: [PATCH 095/102] add support for filtering to indices with errors for
index lifecycle management banner
---
.../components/index_lifecycle_banner.js | 27 ------
.../register_index_lifecycle_banner.js | 22 +++--
.../components/index_table/index_table.js | 84 ++++++++++++-------
.../public/services/filter_items.js | 3 +-
4 files changed, 71 insertions(+), 65 deletions(-)
delete mode 100644 x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_banner.js
diff --git a/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_banner.js b/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_banner.js
deleted file mode 100644
index c492d56571c7b..0000000000000
--- a/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_banner.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License;
- * you may not use this file except in compliance with the Elastic License.
- */
-
-import React from 'react';
-import {
- EuiCallOut,
- EuiText
-} from '@elastic/eui';
-
-export const IndexLifecycleBanner = (props) => {
- const numberOfErroredIndices = props.indices.length;
- return (
-
-
- { numberOfErroredIndices } ind{numberOfErroredIndices > 1 ? 'icies have ' : 'ex has ' } index lifecycle errors.
-
-
- );
-};
\ No newline at end of file
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_banner.js b/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_banner.js
index 0fa78985fc407..32ef838e7b0e2 100644
--- a/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_banner.js
+++ b/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_banner.js
@@ -3,18 +3,30 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
-import React from 'react';
+import { get } from 'lodash';
import { addBannerExtension } from '../../../index_management/public/index_management_extensions';
-import { IndexLifecycleBanner } from '../components/index_lifecycle_banner';
+const stepPath = 'ilm.step';
+import { i18n } from '@kbn/i18n';
+
addBannerExtension((indices) =>{
if (!indices.length) {
return null;
}
const indicesWithLifecycleErrors = indices.filter((index) => {
- return index.ilm && index.ilm.failed_step;
+ return get(index, stepPath) === 'ERROR';
});
- if (!indicesWithLifecycleErrors.length) {
+ const numIndicesWithLifecycleErrors = indicesWithLifecycleErrors.length;
+ if (!numIndicesWithLifecycleErrors) {
return null;
}
- return ;
+ return {
+ type: 'warning',
+ filter: `${stepPath}:ERROR`,
+ message: i18n.translate('xpack.idxLifecycleMgmt.indexMgmtBanner.errorMessage', {
+ defaultMessage: `{ numIndicesWithLifecycleErrors, number}
+ {numIndicesWithLifecycleErrors, plural, one {index has} other {indices have} }
+ lifecycle errors`,
+ values: { numIndicesWithLifecycleErrors }
+ }),
+ };
});
\ No newline at end of file
diff --git a/x-pack/plugins/index_management/public/sections/index_list/components/index_table/index_table.js b/x-pack/plugins/index_management/public/sections/index_list/components/index_table/index_table.js
index 0f7e90ef7eee3..4d9c6b5d95862 100644
--- a/x-pack/plugins/index_management/public/sections/index_list/components/index_table/index_table.js
+++ b/x-pack/plugins/index_management/public/sections/index_list/components/index_table/index_table.js
@@ -4,8 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import React, { Component } from 'react';
-import { i18n } from '@kbn/i18n';
+import React, { Component, Fragment } from 'react';
+import { i18n } from '@kbn/i18n';
import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
import { Route } from 'react-router-dom';
import { NoMatch } from '../../../no_match';
@@ -14,6 +14,8 @@ import { healthToColor } from '../../../../services';
import '../../../../styles/table.less';
import {
+ EuiButtonEmpty,
+ EuiCallOut,
EuiHealth,
EuiLink,
EuiCheckbox,
@@ -35,7 +37,7 @@ import {
EuiTitle,
EuiText,
EuiPageBody,
- EuiPageContent
+ EuiPageContent,
} from '@elastic/eui';
import { IndexActionsContextMenu } from '../../components';
@@ -88,7 +90,7 @@ export class IndexTableUi extends Component {
super(props);
this.state = {
- selectedIndicesMap: {}
+ selectedIndicesMap: {},
};
}
@@ -110,7 +112,7 @@ export class IndexTableUi extends Component {
selectedIndicesMap[name] = true;
});
this.setState({
- selectedIndicesMap
+ selectedIndicesMap,
});
};
@@ -123,7 +125,7 @@ export class IndexTableUi extends Component {
newMap[name] = true;
}
return {
- selectedIndicesMap: newMap
+ selectedIndicesMap: newMap,
};
});
};
@@ -134,9 +136,7 @@ export class IndexTableUi extends Component {
areAllItemsSelected = () => {
const { indices } = this.props;
- const indexOfUnselectedItem = indices.findIndex(
- index => !this.isItemSelected(index.name)
- );
+ const indexOfUnselectedItem = indices.findIndex(index => !this.isItemSelected(index.name));
return indexOfUnselectedItem === -1;
};
@@ -195,8 +195,34 @@ export class IndexTableUi extends Component {
});
}
renderBanners() {
- const { indices = [] } = this.props;
- return getBannerExtensions().map(bannerExtension => bannerExtension(indices));
+ const { indices = [], filterChanged } = this.props;
+ return getBannerExtensions().map(bannerExtension => {
+ const bannerData = bannerExtension(indices);
+ console.log(bannerData);
+ if (!bannerData) {
+ return null;
+ }
+ return (
+
+
+ {bannerData.message} {bannerData.filter ? (
+ {
+ filterChanged(bannerData.filter);
+ }}
+ >
+
+
+ ) : null}
+
+
+
+
+ );
+ });
}
buildRows() {
const { indices = [], detailPanelIndexName } = this.props;
@@ -204,9 +230,7 @@ export class IndexTableUi extends Component {
const { name } = index;
return (
@@ -285,15 +309,17 @@ export class IndexTableUi extends Component {
id="checkboxShowSystemIndices"
checked={showSystemIndices}
onChange={event => showSystemIndicesChanged(event.target.checked)}
- label={}
+ label={
+
+ }
/>
- { this.renderBanners()}
+ {this.renderBanners()}
{atLeastOneItemSelected ? (
@@ -318,18 +344,14 @@ export class IndexTableUi extends Component {
filterChanged(event.target.value);
}}
data-test-subj="indexTableFilterInput"
- placeholder={
- intl.formatMessage({
- id: 'xpack.idxMgmt.indexTable.systemIndicesSearchInputPlaceholder',
- defaultMessage: 'Search',
- })
- }
- aria-label={
- intl.formatMessage({
- id: 'xpack.idxMgmt.indexTable.systemIndicesSearchIndicesAriaLabel',
- defaultMessage: 'Search indices',
- })
- }
+ placeholder={intl.formatMessage({
+ id: 'xpack.idxMgmt.indexTable.systemIndicesSearchInputPlaceholder',
+ defaultMessage: 'Search',
+ })}
+ aria-label={intl.formatMessage({
+ id: 'xpack.idxMgmt.indexTable.systemIndicesSearchIndicesAriaLabel',
+ defaultMessage: 'Search indices',
+ })}
/>
diff --git a/x-pack/plugins/index_management/public/services/filter_items.js b/x-pack/plugins/index_management/public/services/filter_items.js
index 3ec88bf600246..5151f055136c0 100644
--- a/x-pack/plugins/index_management/public/services/filter_items.js
+++ b/x-pack/plugins/index_management/public/services/filter_items.js
@@ -10,10 +10,9 @@ export const filterItems = (fields, filter = '', items = []) => {
return items.filter(item => {
const actualFields = fields || Object.keys(item);
const indexOfMatch = actualFields.findIndex(field => {
- console.log('GETTING', item, field, filter);
const normalizedField = String(get(item, field)).toLowerCase();
console.log('N', normalizedField);
- console.log("MATCH?", normalizedField.includes(lowerFilter));
+ console.log('N', normalizedField);
return normalizedField.includes(lowerFilter);
});
return indexOfMatch !== -1;
From 0a09b0840381968a9de7264a5c5ec3635968f4ce Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 12 Nov 2018 11:15:20 -0500
Subject: [PATCH 096/102] i18n work
---
.../public/components/active_badge.js | 18 +++
.../public/components/index.js | 9 ++
.../components/index_lifecycle_summary.js | 11 +-
.../public/components/phase_error_message.js | 22 +++
.../components/cold_phase/cold_phase.js | 74 ++++++----
.../components/delete_phase/delete_phase.js | 66 ++++++---
.../components/hot_phase/hot_phase.js | 77 ++++++----
.../components/warm_phase/warm_phase.js | 132 +++++++++++++-----
.../sections/edit_policy/edit_policy.js | 57 ++++++--
.../public/store/selectors/lifecycle.js | 57 ++++----
10 files changed, 379 insertions(+), 144 deletions(-)
create mode 100644 x-pack/plugins/index_lifecycle_management/public/components/active_badge.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/components/index.js
create mode 100644 x-pack/plugins/index_lifecycle_management/public/components/phase_error_message.js
diff --git a/x-pack/plugins/index_lifecycle_management/public/components/active_badge.js b/x-pack/plugins/index_lifecycle_management/public/components/active_badge.js
new file mode 100644
index 0000000000000..4696a9a96d5fb
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/components/active_badge.js
@@ -0,0 +1,18 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+import React from 'react';
+import { EuiBadge } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+export const ActiveBadge = () => {
+ return (
+
+
+
+ );
+};
diff --git a/x-pack/plugins/index_lifecycle_management/public/components/index.js b/x-pack/plugins/index_lifecycle_management/public/components/index.js
new file mode 100644
index 0000000000000..9e77b35f5df41
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/components/index.js
@@ -0,0 +1,9 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License;
+ * you may not use this file except in compliance with the Elastic License.
+ */
+
+export { ActiveBadge } from './active_badge';
+export { LearnMoreLink } from './learn_more_link';
+export { PhaseErrorMessage } from './phase_error_message';
\ No newline at end of file
diff --git a/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js b/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js
index 4e38932dab42d..4ecd485c87be5 100644
--- a/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js
+++ b/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js
@@ -15,7 +15,7 @@ import {
EuiSpacer,
EuiTitle
} from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
+import { i18n, FormattedMessage } from '@kbn/i18n';
const HEADERS = {
policy: i18n.translate('xpack.indexLifecycleMgmt.summary.headers.lifecyclePolicyHeader', {
defaultMessage: 'Lifecycle policy',
@@ -82,7 +82,14 @@ export class IndexLifecycleSummary extends Component {
const { left, right } = this.buildRows();
return (
- Index lifecycle management
+
+
+
+
+
diff --git a/x-pack/plugins/index_lifecycle_management/public/components/phase_error_message.js b/x-pack/plugins/index_lifecycle_management/public/components/phase_error_message.js
new file mode 100644
index 0000000000000..c580443dd7ff6
--- /dev/null
+++ b/x-pack/plugins/index_lifecycle_management/public/components/phase_error_message.js
@@ -0,0 +1,22 @@
+/*
+ * 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 { EuiText, EuiTextColor } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+export const PhaseErrorMessage = ({ isShowingErrors }) => {
+ return isShowingErrors ? (
+
+
+
+
+
+
+
+ ) : null;
+};
\ No newline at end of file
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js
index 6ee756c142b61..850a5f51f2605 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js
@@ -6,19 +6,17 @@
import React, { PureComponent, Fragment } from 'react';
import PropTypes from 'prop-types';
+import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
import {
EuiFlexGroup,
EuiFlexItem,
EuiSpacer,
- EuiText,
- EuiTextColor,
EuiFormRow,
EuiFieldNumber,
EuiSelect,
EuiButtonEmpty,
EuiDescribedFormGroup,
- EuiBadge,
EuiButton,
} from '@elastic/eui';
import {
@@ -31,8 +29,9 @@ import {
PHASE_REPLICA_COUNT
} from '../../../../store/constants';
import { ErrableFormRow } from '../../form_errors';
+import { ActiveBadge, PhaseErrorMessage } from '../../../../components';
-export class ColdPhase extends PureComponent {
+class ColdPhaseUi extends PureComponent {
static propTypes = {
setPhaseData: PropTypes.func.isRequired,
showNodeDetailsFlyout: PropTypes.func.isRequired,
@@ -69,16 +68,22 @@ export class ColdPhase extends PureComponent {
nodeOptions,
warmPhaseReplicaCount,
errors,
- isShowingErrors
+ isShowingErrors,
+ intl
} = this.props;
return (
- Cold phase{' '}
+
+
+ {' '}
{phaseData[PHASE_ENABLED] ? (
- Active
+
) : null}
}
@@ -86,16 +91,12 @@ export class ColdPhase extends PureComponent {
description={
- A cold index is queried less frequently
- and thus no longer needs to be on the most performant hardware.
+
- {isShowingErrors ? (
-
-
- This phase contains errors
-
-
- ) : null}
+
}
fullWidth
@@ -111,7 +112,10 @@ export class ColdPhase extends PureComponent {
await setPhaseData(PHASE_ENABLED, false);
}}
>
- Deactive cold phase
+
@@ -120,7 +124,10 @@ export class ColdPhase extends PureComponent {
@@ -154,7 +167,10 @@ export class ColdPhase extends PureComponent {
showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])}
>
- View a list of nodes attached to this configuration
+
) : null}
>
@@ -181,7 +200,10 @@ export class ColdPhase extends PureComponent {
- Activate cold phase
+
)}
@@ -226,3 +251,4 @@ export class ColdPhase extends PureComponent {
);
}
}
+export const ColdPhase = injectI18n(ColdPhaseUi);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js
index 7c4a179ea8935..d5c7da95483a8 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js
@@ -8,6 +8,7 @@
import React, { PureComponent, Fragment } from 'react';
+import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
import PropTypes from 'prop-types';
import {
@@ -15,13 +16,10 @@ import {
EuiFlexItem,
EuiTitle,
EuiSpacer,
- EuiText,
- EuiTextColor,
EuiFormRow,
EuiFieldNumber,
EuiSelect,
EuiDescribedFormGroup,
- EuiBadge,
EuiButton,
} from '@elastic/eui';
import {
@@ -31,8 +29,9 @@ import {
PHASE_ROLLOVER_MINIMUM_AGE_UNITS,
} from '../../../../store/constants';
import { ErrableFormRow } from '../../form_errors';
+import { ActiveBadge, PhaseErrorMessage } from '../../../../components';
-export class DeletePhase extends PureComponent {
+class DeletePhaseUi extends PureComponent {
static propTypes = {
setPhaseData: PropTypes.func.isRequired,
isShowingErrors: PropTypes.bool.isRequired,
@@ -52,16 +51,22 @@ export class DeletePhase extends PureComponent {
setPhaseData,
phaseData,
errors,
- isShowingErrors
+ isShowingErrors,
+ intl
} = this.props;
return (
- Delete phase{' '}
+
+
+ {' '}
{phaseData[PHASE_ENABLED] ? (
- Active
+
) : null}
}
@@ -69,15 +74,13 @@ export class DeletePhase extends PureComponent {
description={
- Use this phase to define how long to retain your data.
+
+
- {isShowingErrors ? (
-
-
- This phase contains errors
-
-
- ) : null}
+
}
fullWidth
@@ -93,20 +96,31 @@ export class DeletePhase extends PureComponent {
await setPhaseData(PHASE_ENABLED, false);
}}
>
- Deactive delete phase
+
- Configuration
+
+
+
@@ -144,7 +164,10 @@ export class DeletePhase extends PureComponent {
await setPhaseData(PHASE_ENABLED, true);
}}
>
- Activate delete phase
+
)}
@@ -152,3 +175,4 @@ export class DeletePhase extends PureComponent {
);
}
}
+export const DeletePhase = injectI18n(DeletePhaseUi);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js
index ef88d4cae15ab..64be10ef4fc09 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js
@@ -5,22 +5,20 @@
*/
import React, { Fragment, PureComponent } from 'react';
+import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
import PropTypes from 'prop-types';
import {
EuiFlexGroup,
EuiFlexItem,
EuiSpacer,
- EuiText,
- EuiTextColor,
EuiFieldNumber,
EuiSelect,
EuiSwitch,
EuiFormRow,
EuiDescribedFormGroup,
- EuiBadge,
} from '@elastic/eui';
-import { LearnMoreLink } from '../../../../components/learn_more_link';
+import { LearnMoreLink, ActiveBadge, PhaseErrorMessage } from '../../../../components';
import {
PHASE_HOT,
PHASE_ROLLOVER_ALIAS,
@@ -34,7 +32,7 @@ import {
import { ErrableFormRow } from '../../form_errors';
-export class HotPhase extends PureComponent {
+class HotPhaseUi extends PureComponent {
static propTypes = {
setPhaseData: PropTypes.func.isRequired,
@@ -61,30 +59,33 @@ export class HotPhase extends PureComponent {
phaseData,
isShowingErrors,
errors,
+ intl
} = this.props;
return (
- Hot phase{' '}
- Active
+
+
+ {' '}
+
}
titleSize="s"
description={
- This phase is required. A hot index is being queried and actively written to.
- You can optimize this phase for write throughput.
+
- {isShowingErrors ? (
-
-
- This phase contains errors
-
-
- ) : null}
+
}
fullWidth
@@ -93,9 +94,13 @@ export class HotPhase extends PureComponent {
hasEmptyLabelSpace
helpText={
- If true, rollover the index when it gets too big or too old. The alias switches to the new index.{' '}
+
+ {' '}
}
@@ -105,7 +110,10 @@ export class HotPhase extends PureComponent {
onChange={async e => {
await setPhaseData(PHASE_ROLLOVER_ENABLED, e.target.checked);
}}
- label="Enable rollover"
+ label={intl.formatMessage({
+ id: 'xpack.idxLifecycleMgmt.hotPhase.enableRolloverLabel',
+ defaultMessage: 'Enable rollover'
+ })}
/>
{phaseData[PHASE_ROLLOVER_ENABLED] ? (
@@ -115,7 +123,10 @@ export class HotPhase extends PureComponent {
@@ -161,7 +178,10 @@ export class HotPhase extends PureComponent {
@@ -205,3 +231,4 @@ export class HotPhase extends PureComponent {
);
}
}
+export const HotPhase = injectI18n(HotPhaseUi);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
index dc3768451330d..6ef2189f9be9f 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
@@ -5,21 +5,20 @@
*/
import React, { Fragment, PureComponent } from 'react';
+import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
import PropTypes from 'prop-types';
import {
+ EuiTextColor,
EuiFlexGroup,
EuiFlexItem,
EuiTitle,
EuiSpacer,
- EuiText,
- EuiTextColor,
EuiFormRow,
EuiFieldNumber,
EuiSelect,
EuiSwitch,
EuiButtonEmpty,
EuiDescribedFormGroup,
- EuiBadge,
EuiButton,
} from '@elastic/eui';
import {
@@ -37,9 +36,9 @@ import {
PHASE_SHRINK_ENABLED,
} from '../../../../store/constants';
import { ErrableFormRow } from '../../form_errors';
-import { LearnMoreLink } from '../../../../components/learn_more_link';
+import { LearnMoreLink, ActiveBadge, PhaseErrorMessage } from '../../../../components';
-export class WarmPhase extends PureComponent {
+class WarmPhaseUi extends PureComponent {
static propTypes = {
setPhaseData: PropTypes.func.isRequired,
showNodeDetailsFlyout: PropTypes.func.isRequired,
@@ -76,15 +75,21 @@ export class WarmPhase extends PureComponent {
errors,
isShowingErrors,
hotPhaseRolloverEnabled,
+ intl
} = this.props;
return (
- Warm phase{' '}
+
+
+ {' '}
{phaseData[PHASE_ENABLED] ? (
- Active
+
) : null}
}
@@ -92,16 +97,12 @@ export class WarmPhase extends PureComponent {
description={
- Your index becomes read-only when it enters the warm phase. You can optimize this
- phase for search.
+
- {isShowingErrors ? (
-
-
- This phase contains errors
-
-
- ) : null}
+
}
fullWidth
@@ -117,14 +118,25 @@ export class WarmPhase extends PureComponent {
await setPhaseData(PHASE_ENABLED, false);
}}
>
- Deactivate warm phase
+
{hotPhaseRolloverEnabled ? (
-
+
{
await setPhaseData(WARM_PHASE_ON_ROLLOVER, e.target.checked);
@@ -137,7 +149,10 @@ export class WarmPhase extends PureComponent {
@@ -172,7 +193,10 @@ export class WarmPhase extends PureComponent {
showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])}
>
- View node details
+
) : null
}
@@ -200,7 +227,10 @@ export class WarmPhase extends PureComponent {
- Shrink
+
+
+
- Shrink the index into a new index with fewer primary shards.{' '}
+ {' '}
@@ -236,7 +274,10 @@ export class WarmPhase extends PureComponent {
onChange={async e => {
await setPhaseData(PHASE_SHRINK_ENABLED, e.target.checked);
}}
- label="Shrink index"
+ label={intl.formatMessage({
+ id: 'xpack.idxLifecycleMgmt.warmPhase.shrinkIndexLabel',
+ defaultMessage: 'Shrink index'
+ })}
/>
{phaseData[PHASE_SHRINK_ENABLED] ? (
@@ -245,7 +286,10 @@ export class WarmPhase extends PureComponent {
- Force merge
+
+
+
- Reduce the number of segments in your shard by merging smaller files and clearing
- deleted ones.
+
+ {' '}
{
await setPhaseData(PHASE_FORCE_MERGE_ENABLED, e.target.checked);
@@ -290,7 +345,10 @@ export class WarmPhase extends PureComponent {
{phaseData[PHASE_FORCE_MERGE_ENABLED] ? (
- Activate warm phase
+
@@ -323,3 +384,4 @@ export class WarmPhase extends PureComponent {
);
}
}
+export const WarmPhase = injectI18n(WarmPhaseUi);
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
index 9715953c53d3b..1d3ddc29f2fd8 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
@@ -8,7 +8,7 @@ import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { toastNotifications } from 'ui/notify';
import { goToPolicyList } from '../../services/navigation';
-
+import { FormattedMessage, injectI18n } from '@kbn/i18n/react';
import {
EuiPage,
EuiPageBody,
@@ -38,7 +38,7 @@ import { findFirstError } from '../../lib/find_errors';
import { NodeAttrsDetails } from './components/node_attrs_details';
import { ErrableFormRow } from './form_errors';
-export class EditPolicy extends Component {
+class EditPolicyUi extends Component {
static propTypes = {
selectedPolicy: PropTypes.object.isRequired,
errors: PropTypes.object.isRequired,
@@ -85,6 +85,7 @@ export class EditPolicy extends Component {
goToPolicyList();
}
submit = async () => {
+ const { intl } = this.props;
this.setState({ isShowingErrors: true });
const {
saveLifecyclePolicy,
@@ -93,7 +94,10 @@ export class EditPolicy extends Component {
firstError
} = this.props;
if (firstError) {
- toastNotifications.addDanger('Please the fix errors on the page');
+ toastNotifications.addDanger(intl.formatMessage({
+ id: 'xpack.idxLifecycleMgmt.editPolicy.formErrorsMessage',
+ defaultMessage: 'Please the fix errors on the page'
+ }));
const element = document.getElementById(`${firstError}-row`);
if (element) {
element.scrollIntoView();
@@ -111,6 +115,7 @@ export class EditPolicy extends Component {
};
render() {
const {
+ intl,
selectedPolicy,
errors,
match: {
@@ -135,8 +140,14 @@ export class EditPolicy extends Component {
{isNewPolicy
- ? 'Create an index lifecycle policy'
- : `Edit index lifecycle policy ${selectedPolicyName}`}
+ ? intl.formatMessage({
+ id: 'xpack.idxLifecycleMgmt.editPolicy.createPolicyMessage',
+ defaultMessage: 'Create an index lifecycle policy'
+ })
+ : intl.formatMessage({
+ id: 'xpack.idxLifecycleMgmt.editPolicy.editPolicyMessage',
+ defaultMessage: 'Edit index lifecycle policy {selectedPolicyName}',
+ }, { selectedPolicyName }) }
@@ -151,10 +162,17 @@ export class EditPolicy extends Component {
- You are editing an existing policy. Any changes you make
- will also change index templates that this policy is attached to.
- Alternately, you can save these changes in a new policy and only change
- the index template you selected.
+
+
+ .{' '}
+
@@ -169,7 +187,10 @@ export class EditPolicy extends Component {
}}
label={
- Save this as a new policy
+
}
/>
@@ -181,7 +202,10 @@ export class EditPolicy extends Component {
- Cancel
+
- Save your policy
+
{this.state.isShowingNodeDetailsFlyout ? (
{
const phaseErrors = {};
@@ -46,10 +50,14 @@ export const validatePhase = (type, phase, errors) => {
!isNumber(phase[PHASE_ROLLOVER_MAX_SIZE_STORED])
) {
phaseErrors[PHASE_ROLLOVER_MAX_AGE] = [
- 'A maximum age is required'
+ i18n.translate('xpack.idxLifecycleMgmt.editPolicy.maximumAgeMissingError', {
+ defaultMessage: 'A maximum age is required'
+ })
];
phaseErrors[PHASE_ROLLOVER_MAX_SIZE_STORED] = [
- 'A maximum index size is required'
+ i18n.translate('xpack.idxLifecycleMgmt.editPolicy.maximumIndexSizeMissingError', {
+ defaultMessage: 'A maximum index size is required'
+ })
];
}
}
@@ -61,32 +69,36 @@ export const validatePhase = (type, phase, errors) => {
continue;
}
if (!isNumber(phase[numberedAttribute])) {
- phaseErrors[numberedAttribute] = ['A number is required'];
+ phaseErrors[numberedAttribute] = [numberRequiredMessage];
}
else if (phase[numberedAttribute] < 0) {
- phaseErrors[numberedAttribute] = ['Only positive numbers are allowed'];
+ phaseErrors[numberedAttribute] = [positiveNumberRequiredMessage];
}
else if (numberedAttribute === PHASE_PRIMARY_SHARD_COUNT && phase[numberedAttribute] < 1) {
- phaseErrors[numberedAttribute] = ['Only positive numbers are allowed'];
+ phaseErrors[numberedAttribute] = [positiveNumberRequiredMessage];
}
}
}
if (phase[PHASE_SHRINK_ENABLED]) {
if (!isNumber(phase[PHASE_PRIMARY_SHARD_COUNT])) {
- phaseErrors[PHASE_PRIMARY_SHARD_COUNT] = ['A number is required.'];
+ phaseErrors[PHASE_PRIMARY_SHARD_COUNT] = [numberRequiredMessage];
}
else if (phase[PHASE_PRIMARY_SHARD_COUNT] < 1) {
- phaseErrors[PHASE_PRIMARY_SHARD_COUNT] = ['Only positive numbers are allowed.'];
+ phaseErrors[PHASE_PRIMARY_SHARD_COUNT] = [positiveNumberRequiredMessage];
}
}
if (phase[PHASE_FORCE_MERGE_ENABLED]) {
if (!isNumber(phase[PHASE_FORCE_MERGE_SEGMENTS])) {
- phaseErrors[PHASE_FORCE_MERGE_SEGMENTS] = ['A number is required.'];
+ phaseErrors[PHASE_FORCE_MERGE_SEGMENTS] = [numberRequiredMessage];
}
else if (phase[PHASE_FORCE_MERGE_SEGMENTS] < 1) {
- phaseErrors[PHASE_FORCE_MERGE_SEGMENTS] = ['Only positive numbers above 0 are allowed.'];
+ phaseErrors[PHASE_FORCE_MERGE_SEGMENTS] = [
+ i18n.translate('xpack.idxLifecycleMgmt.editPolicy.positiveNumberAboveZeroRequiredError', {
+ defaultMessage: 'Only positive numbers above 0 are allowed'
+ })
+ ];
}
}
errors[type] = {
@@ -100,17 +112,23 @@ export const validateLifecycle = state => {
const errors = JSON.parse(JSON.stringify(ERROR_STRUCTURE));
if (!getSelectedPolicyName(state)) {
- errors[STRUCTURE_POLICY_NAME].push('A policy name is required');
+ errors[STRUCTURE_POLICY_NAME].push(i18n.translate('xpack.idxLifecycleMgmt.editPolicy.policyNameRequiredError', {
+ defaultMessage: 'A policy name is required'
+ }));
}
if (getSaveAsNewPolicy(state) && getSelectedOriginalPolicyName(state) === getSelectedPolicyName(state)) {
- errors[STRUCTURE_POLICY_NAME].push('The policy name must be different');
+ errors[STRUCTURE_POLICY_NAME].push(i18n.translate('xpack.idxLifecycleMgmt.editPolicy.differentPolicyNameRequiredError', {
+ defaultMessage: 'The policy name must be different'
+ }));
}
if (getSaveAsNewPolicy(state)) {
const policyNames = getPolicies(state).map(policy => policy.name);
if (policyNames.includes(getSelectedPolicyName(state))) {
- errors[STRUCTURE_POLICY_NAME].push('That policy name is already used.');
+ errors[STRUCTURE_POLICY_NAME].push(i18n.translate('xpack.idxLifecycleMgmt.editPolicy.policyNameAlreadyUsedError', {
+ defaultMessage: 'That policy name is already used'
+ }));
}
}
@@ -123,15 +141,6 @@ export const validateLifecycle = state => {
validatePhase(PHASE_WARM, warmPhase, errors);
validatePhase(PHASE_COLD, coldPhase, errors);
validatePhase(PHASE_DELETE, deletePhase, errors);
- if (warmPhase[PHASE_SHRINK_ENABLED]) {
- if (isNumber(warmPhase[PHASE_PRIMARY_SHARD_COUNT]) && warmPhase[PHASE_PRIMARY_SHARD_COUNT] > 0) {
- if (getSelectedPrimaryShardCount(state) % warmPhase[PHASE_PRIMARY_SHARD_COUNT] !== 0) {
- errors[PHASE_WARM][PHASE_PRIMARY_SHARD_COUNT].push(
- 'The shard count needs to be a divisor of the hot phase shard count.'
- );
- }
- }
- }
return errors;
};
From d3e50a708ece5d79e56538be5ec7c0709486c7c1 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 12 Nov 2018 11:54:01 -0500
Subject: [PATCH 097/102] fixing error wrappers
---
.../server/lib/error_wrappers/wrap_custom_error.js | 2 +-
.../server/lib/error_wrappers/wrap_es_error.js | 4 ++--
.../server/lib/error_wrappers/wrap_unknown_error.js | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_custom_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_custom_error.js
index 890a366ac65c1..3295113d38ee5 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_custom_error.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_custom_error.js
@@ -14,5 +14,5 @@ import Boom from 'boom';
* @return Object Boom error response
*/
export function wrapCustomError(err, statusCode) {
- return Boom.wrap(err, statusCode);
+ return Boom.boomify(err, { statusCode });
}
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.js
index 9f1328219bab2..2df2e4b802e1a 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_es_error.js
@@ -20,11 +20,11 @@ export function wrapEsError(err, statusCodeToMessageMap = {}) {
// 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, err.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 Boom.create(statusCode, message);
+ return new Boom(message, { statusCode });
}
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_unknown_error.js b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_unknown_error.js
index b0cdced7adbef..4b865880ae20d 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_unknown_error.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/error_wrappers/wrap_unknown_error.js
@@ -13,5 +13,5 @@ import Boom from 'boom';
* @return Object Boom error response
*/
export function wrapUnknownError(err) {
- return Boom.wrap(err);
-}
+ return Boom.boomify(err);
+}
\ No newline at end of file
From 01256bdceeba8013caac0d8c4939bcc7ea602099 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 12 Nov 2018 12:42:09 -0500
Subject: [PATCH 098/102] fixing tests
---
.../__tests__/license_pre_routing_factory.js | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
index b72f8cc769731..359b3fb2ce6f4 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/__tests__/license_pre_routing_factory.js
@@ -40,14 +40,13 @@ describe('license_pre_routing_factory', () => {
};
});
- it ('replies with 403', (done) => {
+ it ('replies with 403', () => {
const licensePreRouting = licensePreRoutingFactory(mockServer);
const stubRequest = {};
- licensePreRouting(stubRequest, (response) => {
+ 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);
- done();
});
});
});
@@ -59,13 +58,11 @@ describe('license_pre_routing_factory', () => {
};
});
- it ('replies with nothing', (done) => {
+ it ('replies with nothing', () => {
const licensePreRouting = licensePreRoutingFactory(mockServer);
const stubRequest = {};
- licensePreRouting(stubRequest, (response) => {
- expect(response).to.be(undefined);
- done();
- });
+ const response = licensePreRouting(stubRequest);
+ expect(response).to.be(null);
});
});
});
From 25e0fc1bf8479a218a1ff2fd8b2bfdac51c61913 Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 12 Nov 2018 13:24:10 -0500
Subject: [PATCH 099/102] adding view JSON for index lifecycle policy on edit
screen
---
.../public/components/active_badge.js | 2 +-
.../components/index_lifecycle_summary.js | 2 +-
.../public/components/phase_error_message.js | 2 +-
.../register_index_lifecycle_banner.js | 2 +-
.../components/cold_phase/cold_phase.js | 20 +++---
.../components/delete_phase/delete_phase.js | 16 ++---
.../components/hot_phase/hot_phase.js | 20 +++---
.../components/policy_json_flyout.js | 66 +++++++++++++++++++
.../components/warm_phase/warm_phase.js | 40 +++++------
.../sections/edit_policy/edit_policy.js | 37 ++++++++---
.../public/store/selectors/lifecycle.js | 16 ++---
11 files changed, 154 insertions(+), 69 deletions(-)
create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/policy_json_flyout.js
diff --git a/x-pack/plugins/index_lifecycle_management/public/components/active_badge.js b/x-pack/plugins/index_lifecycle_management/public/components/active_badge.js
index 4696a9a96d5fb..4a270c9e002f0 100644
--- a/x-pack/plugins/index_lifecycle_management/public/components/active_badge.js
+++ b/x-pack/plugins/index_lifecycle_management/public/components/active_badge.js
@@ -10,7 +10,7 @@ export const ActiveBadge = () => {
return (
diff --git a/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js b/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js
index 4ecd485c87be5..77f87be1da824 100644
--- a/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js
+++ b/x-pack/plugins/index_lifecycle_management/public/components/index_lifecycle_summary.js
@@ -86,7 +86,7 @@ export class IndexLifecycleSummary extends Component {
diff --git a/x-pack/plugins/index_lifecycle_management/public/components/phase_error_message.js b/x-pack/plugins/index_lifecycle_management/public/components/phase_error_message.js
index c580443dd7ff6..3466f09168b0a 100644
--- a/x-pack/plugins/index_lifecycle_management/public/components/phase_error_message.js
+++ b/x-pack/plugins/index_lifecycle_management/public/components/phase_error_message.js
@@ -12,7 +12,7 @@ export const PhaseErrorMessage = ({ isShowingErrors }) => {
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_banner.js b/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_banner.js
index 32ef838e7b0e2..519c9b78518b4 100644
--- a/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_banner.js
+++ b/x-pack/plugins/index_lifecycle_management/public/register_index_management_extensions/register_index_lifecycle_banner.js
@@ -22,7 +22,7 @@ addBannerExtension((indices) =>{
return {
type: 'warning',
filter: `${stepPath}:ERROR`,
- message: i18n.translate('xpack.idxLifecycleMgmt.indexMgmtBanner.errorMessage', {
+ message: i18n.translate('xpack.indexLifecycleMgmt.indexMgmtBanner.errorMessage', {
defaultMessage: `{ numIndicesWithLifecycleErrors, number}
{numIndicesWithLifecycleErrors, plural, one {index has} other {indices have} }
lifecycle errors`,
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js
index 850a5f51f2605..92973ad3a0e38 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/cold_phase/cold_phase.js
@@ -78,7 +78,7 @@ class ColdPhaseUi extends PureComponent {
{' '}
@@ -92,7 +92,7 @@ class ColdPhaseUi extends PureComponent {
@@ -113,7 +113,7 @@ class ColdPhaseUi extends PureComponent {
}}
>
@@ -125,7 +125,7 @@ class ColdPhaseUi extends PureComponent {
showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])}
>
@@ -201,7 +201,7 @@ class ColdPhaseUi extends PureComponent {
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js
index d5c7da95483a8..d15d794a277bc 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/delete_phase/delete_phase.js
@@ -61,7 +61,7 @@ class DeletePhaseUi extends PureComponent {
{' '}
@@ -75,7 +75,7 @@ class DeletePhaseUi extends PureComponent {
@@ -97,7 +97,7 @@ class DeletePhaseUi extends PureComponent {
}}
>
@@ -107,7 +107,7 @@ class DeletePhaseUi extends PureComponent {
@@ -118,7 +118,7 @@ class DeletePhaseUi extends PureComponent {
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js
index 64be10ef4fc09..19fcb8507b8d5 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/hot_phase/hot_phase.js
@@ -68,7 +68,7 @@ class HotPhaseUi extends PureComponent {
{' '}
@@ -80,7 +80,7 @@ class HotPhaseUi extends PureComponent {
@@ -95,7 +95,7 @@ class HotPhaseUi extends PureComponent {
helpText={
{' '}
@@ -111,7 +111,7 @@ class HotPhaseUi extends PureComponent {
await setPhaseData(PHASE_ROLLOVER_ENABLED, e.target.checked);
}}
label={intl.formatMessage({
- id: 'xpack.idxLifecycleMgmt.hotPhase.enableRolloverLabel',
+ id: 'xpack.indexLifecycleMgmt.hotPhase.enableRolloverLabel',
defaultMessage: 'Enable rollover'
})}
/>
@@ -124,7 +124,7 @@ class HotPhaseUi extends PureComponent {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+export const PolicyJsonFlyout = injectI18n(PolicyJsonFlyoutUi);
+
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
index 6ef2189f9be9f..abc012ca590df 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/warm_phase/warm_phase.js
@@ -84,7 +84,7 @@ class WarmPhaseUi extends PureComponent {
{' '}
@@ -98,7 +98,7 @@ class WarmPhaseUi extends PureComponent {
@@ -119,7 +119,7 @@ class WarmPhaseUi extends PureComponent {
}}
>
@@ -128,13 +128,13 @@ class WarmPhaseUi extends PureComponent {
{hotPhaseRolloverEnabled ? (
showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])}
>
@@ -228,7 +228,7 @@ class WarmPhaseUi extends PureComponent {
@@ -260,7 +260,7 @@ class WarmPhaseUi extends PureComponent {
{' '}
@@ -275,7 +275,7 @@ class WarmPhaseUi extends PureComponent {
await setPhaseData(PHASE_SHRINK_ENABLED, e.target.checked);
}}
label={intl.formatMessage({
- id: 'xpack.idxLifecycleMgmt.warmPhase.shrinkIndexLabel',
+ id: 'xpack.indexLifecycleMgmt.warmPhase.shrinkIndexLabel',
defaultMessage: 'Shrink index'
})}
/>
@@ -287,7 +287,7 @@ class WarmPhaseUi extends PureComponent {
@@ -320,7 +320,7 @@ class WarmPhaseUi extends PureComponent {
{' '}
@@ -331,7 +331,7 @@ class WarmPhaseUi extends PureComponent {
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
index 1d3ddc29f2fd8..d81f517fce816 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/edit_policy.js
@@ -36,6 +36,7 @@ import {
} from '../../store/constants';
import { findFirstError } from '../../lib/find_errors';
import { NodeAttrsDetails } from './components/node_attrs_details';
+import { PolicyJsonFlyout } from './components/policy_json_flyout';
import { ErrableFormRow } from './form_errors';
class EditPolicyUi extends Component {
@@ -50,6 +51,7 @@ class EditPolicyUi extends Component {
isShowingErrors: false,
isShowingNodeDetailsFlyout: false,
selectedNodeAttrsForDetails: undefined,
+ isShowingPolicyJsonFlyout: false
};
}
selectPolicy = policyName => {
@@ -95,7 +97,7 @@ class EditPolicyUi extends Component {
} = this.props;
if (firstError) {
toastNotifications.addDanger(intl.formatMessage({
- id: 'xpack.idxLifecycleMgmt.editPolicy.formErrorsMessage',
+ id: 'xpack.indexLifecycleMgmt.editPolicy.formErrorsMessage',
defaultMessage: 'Please the fix errors on the page'
}));
const element = document.getElementById(`${firstError}-row`);
@@ -113,6 +115,9 @@ class EditPolicyUi extends Component {
showNodeDetailsFlyout = selectedNodeAttrsForDetails => {
this.setState({ isShowingNodeDetailsFlyout: true, selectedNodeAttrsForDetails });
};
+ showPolicyJsonFlyout = () => {
+ this.setState({ isShowingPolicyJsonFlyout: true });
+ };
render() {
const {
intl,
@@ -125,6 +130,7 @@ class EditPolicyUi extends Component {
saveAsNewPolicy,
setSelectedPolicyName,
isNewPolicy,
+ lifecycle
} = this.props;
const selectedPolicyName = selectedPolicy.name;
const { isShowingErrors } = this.state;
@@ -141,11 +147,11 @@ class EditPolicyUi extends Component {
{isNewPolicy
? intl.formatMessage({
- id: 'xpack.idxLifecycleMgmt.editPolicy.createPolicyMessage',
+ id: 'xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage',
defaultMessage: 'Create an index lifecycle policy'
})
: intl.formatMessage({
- id: 'xpack.idxLifecycleMgmt.editPolicy.editPolicyMessage',
+ id: 'xpack.indexLifecycleMgmt.editPolicy.editPolicyMessage',
defaultMessage: 'Edit index lifecycle policy {selectedPolicyName}',
}, { selectedPolicyName }) }
@@ -164,12 +170,12 @@ class EditPolicyUi extends Component {
.{' '}
@@ -188,7 +194,7 @@ class EditPolicyUi extends Component {
label={
@@ -203,7 +209,7 @@ class EditPolicyUi extends Component {
+
+
+
{this.state.isShowingNodeDetailsFlyout ? (
this.setState({ isShowingNodeDetailsFlyout: false })}
/>
) : null}
+ {this.state.isShowingPolicyJsonFlyout ? (
+ this.setState({ isShowingPolicyJsonFlyout: false })}
+ />
+ ) : null}
diff --git a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
index 782d2747c21ca..9d44cd4ae5b5e 100644
--- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
+++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/lifecycle.js
@@ -31,10 +31,10 @@ import {
getSelectedOriginalPolicyName,
getPolicies
} from '.';
-const numberRequiredMessage = i18n.translate('xpack.idxLifecycleMgmt.editPolicy.numberRequiredError', {
+const numberRequiredMessage = i18n.translate('xpack.indexLifecycleMgmt.editPolicy.numberRequiredError', {
defaultMessage: 'A number is required'
});
-const positiveNumberRequiredMessage = i18n.translate('xpack.idxLifecycleMgmt.editPolicy.positiveNumberRequiredError', {
+const positiveNumberRequiredMessage = i18n.translate('xpack.indexLifecycleMgmt.editPolicy.positiveNumberRequiredError', {
defaultMessage: 'Only positive numbers are allowed'
});
export const validatePhase = (type, phase, errors) => {
@@ -50,12 +50,12 @@ export const validatePhase = (type, phase, errors) => {
!isNumber(phase[PHASE_ROLLOVER_MAX_SIZE_STORED])
) {
phaseErrors[PHASE_ROLLOVER_MAX_AGE] = [
- i18n.translate('xpack.idxLifecycleMgmt.editPolicy.maximumAgeMissingError', {
+ i18n.translate('xpack.indexLifecycleMgmt.editPolicy.maximumAgeMissingError', {
defaultMessage: 'A maximum age is required'
})
];
phaseErrors[PHASE_ROLLOVER_MAX_SIZE_STORED] = [
- i18n.translate('xpack.idxLifecycleMgmt.editPolicy.maximumIndexSizeMissingError', {
+ i18n.translate('xpack.indexLifecycleMgmt.editPolicy.maximumIndexSizeMissingError', {
defaultMessage: 'A maximum index size is required'
})
];
@@ -95,7 +95,7 @@ export const validatePhase = (type, phase, errors) => {
}
else if (phase[PHASE_FORCE_MERGE_SEGMENTS] < 1) {
phaseErrors[PHASE_FORCE_MERGE_SEGMENTS] = [
- i18n.translate('xpack.idxLifecycleMgmt.editPolicy.positiveNumberAboveZeroRequiredError', {
+ i18n.translate('xpack.indexLifecycleMgmt.editPolicy.positiveNumberAboveZeroRequiredError', {
defaultMessage: 'Only positive numbers above 0 are allowed'
})
];
@@ -112,13 +112,13 @@ export const validateLifecycle = state => {
const errors = JSON.parse(JSON.stringify(ERROR_STRUCTURE));
if (!getSelectedPolicyName(state)) {
- errors[STRUCTURE_POLICY_NAME].push(i18n.translate('xpack.idxLifecycleMgmt.editPolicy.policyNameRequiredError', {
+ errors[STRUCTURE_POLICY_NAME].push(i18n.translate('xpack.indexLifecycleMgmt.editPolicy.policyNameRequiredError', {
defaultMessage: 'A policy name is required'
}));
}
if (getSaveAsNewPolicy(state) && getSelectedOriginalPolicyName(state) === getSelectedPolicyName(state)) {
- errors[STRUCTURE_POLICY_NAME].push(i18n.translate('xpack.idxLifecycleMgmt.editPolicy.differentPolicyNameRequiredError', {
+ errors[STRUCTURE_POLICY_NAME].push(i18n.translate('xpack.indexLifecycleMgmt.editPolicy.differentPolicyNameRequiredError', {
defaultMessage: 'The policy name must be different'
}));
}
@@ -126,7 +126,7 @@ export const validateLifecycle = state => {
if (getSaveAsNewPolicy(state)) {
const policyNames = getPolicies(state).map(policy => policy.name);
if (policyNames.includes(getSelectedPolicyName(state))) {
- errors[STRUCTURE_POLICY_NAME].push(i18n.translate('xpack.idxLifecycleMgmt.editPolicy.policyNameAlreadyUsedError', {
+ errors[STRUCTURE_POLICY_NAME].push(i18n.translate('xpack.indexLifecycleMgmt.editPolicy.policyNameAlreadyUsedError', {
defaultMessage: 'That policy name is already used'
}));
}
From 562acc5fbdc11575a2cbc16a322298995365f90a Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 12 Nov 2018 13:25:14 -0500
Subject: [PATCH 100/102] fixing label for i18n on policy JSON flyout
---
.../sections/edit_policy/components/policy_json_flyout.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/policy_json_flyout.js b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/policy_json_flyout.js
index a61611db6cb06..cd8ddfd372551 100644
--- a/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/policy_json_flyout.js
+++ b/x-pack/plugins/index_lifecycle_management/public/sections/edit_policy/components/policy_json_flyout.js
@@ -52,7 +52,7 @@ export class PolicyJsonFlyoutUi extends PureComponent {
From a40716af22ff2e3792fda09c188d1ed4f0685efa Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 12 Nov 2018 13:27:01 -0500
Subject: [PATCH 101/102] removing console.log statements
---
.../index_lifecycle_management/public/lib/find_errors.js | 5 -----
.../index_lifecycle_management/public/register_routes.js | 1 -
2 files changed, 6 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/find_errors.js b/x-pack/plugins/index_lifecycle_management/public/lib/find_errors.js
index 6a95326ee85c9..7b77cf7a1301c 100644
--- a/x-pack/plugins/index_lifecycle_management/public/lib/find_errors.js
+++ b/x-pack/plugins/index_lifecycle_management/public/lib/find_errors.js
@@ -5,25 +5,20 @@
*/
export const findFirstError = (object, topLevel = true) => {
- console.log("ERRORS", object);
-
let firstError;
const keys = topLevel ? [ 'policyName', 'hot', 'warm', 'cold', 'delete'] : Object.keys(object);
for (const key of keys) {
const value = object[key];
if (Array.isArray(value) && value.length > 0) {
firstError = key;
- console.log(`Found error ${firstError}`);
break;
} else if (value) {
firstError = findFirstError(value, false);
if (firstError) {
firstError = `${key}.${firstError}`;
- console.log(`Found error ${firstError}`);
break;
}
}
}
- console.log(`Returning ${firstError}`);
return firstError;
};
diff --git a/x-pack/plugins/index_lifecycle_management/public/register_routes.js b/x-pack/plugins/index_lifecycle_management/public/register_routes.js
index 27a26b98f503b..ebb37c9b76a51 100644
--- a/x-pack/plugins/index_lifecycle_management/public/register_routes.js
+++ b/x-pack/plugins/index_lifecycle_management/public/register_routes.js
@@ -37,7 +37,6 @@ if (chrome.getInjected('indexLifecycleManagementUiEnabled')) {
controllerAs: 'indexLifecycleManagement',
controller: class IndexLifecycleManagementController {
constructor($scope, $route, $http, kbnUrl, $rootScope) {
- console.log("ILM");
setHttpClient($http);
setUrlService({
change(url) {
From 03c439738b1650ea838d0da720866db307a77aac Mon Sep 17 00:00:00 2001
From: Bill McConaghy
Date: Mon, 12 Nov 2018 13:33:41 -0500
Subject: [PATCH 102/102] fixing tests
---
.../license_pre_routing_factory.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js
index abfc7fc24dcc3..11e01304b6e5c 100644
--- a/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js
+++ b/x-pack/plugins/index_lifecycle_management/server/lib/license_pre_routing_factory/license_pre_routing_factory.js
@@ -17,9 +17,9 @@ export const licensePreRoutingFactory = once((server) => {
if (!licenseCheckResults.isAvailable) {
const error = new Error(licenseCheckResults.message);
const statusCode = 403;
- const wrappedError = wrapCustomError(error, statusCode);
- return wrappedError;
+ throw wrapCustomError(error, statusCode);
}
+
return null;
}