From 1b421cc2baa6e85e160f5b497add2dd4e6245796 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Fri, 27 Apr 2018 09:16:48 -0400 Subject: [PATCH 01/62] 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 02/62] 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 03/62] 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):

    {affectedIndexTemplates.map(template => ( @@ -108,7 +106,8 @@ export class Review extends Component {

    - Indices affected by this change (to the selected policy): + Indices affected by this change (to the + selected policy):

      {affectedIndices.map(index =>
    • {index}
    • )} @@ -123,14 +122,9 @@ export class Review extends Component {

      New alias

      -

      Point to these new aliases going forward:

      +

      Point to this new alias going forward:

        -
      • - READ: {aliasName} -
      • -
      • - WRITE: {aliasName} -
      • +
      • {aliasName}
      @@ -138,30 +132,35 @@ export class Review extends Component { ) : null} - -

      - We will be changing the index template named `{ - selectedIndexTemplateName - }` -

      -
      - - - + {templateDiff.hasChanged ? ( + + +

      + We will be changing the index template named `{ + selectedIndexTemplateName + }` +

      +
      + + + + +
      + ) : null} { return indexPatterns; }; +// const hasJSONChanged = (json1, json2) => JSON.stringify(json1) !== JSON.stringify(json2); 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), - } + const originalFullIndexTemplate = getFullSelectedIndexTemplate(state) || { settings: {} }; + const newFullIndexTemplate = merge(cloneDeep(originalFullIndexTemplate), { + 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), - // } - // } - // } - // } + } + }); + + return { + originalFullIndexTemplate, + newFullIndexTemplate, + hasChanged: true//hasJSONChanged(originalFullIndexTemplate, newFullIndexTemplate), }; }; From ecdfeabdd69e56cd18c68befd931165b53e85909 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 30 Apr 2018 14:22:55 -0400 Subject: [PATCH 04/62] Fix errors and add flyout for node details --- .../public/api/index.js | 5 + .../public/lib/find_errors.js | 13 ++- .../components/configuration/configuration.js | 96 ++++++++++++------- .../components/node_attrs_details/index.js | 7 ++ .../node_attrs_details.container.js | 17 ++++ .../node_attrs_details/node_attrs_details.js | 77 +++++++++++++++ .../components/cold_phase/cold_phase.js | 48 +++++++--- .../components/warm_phase/warm_phase.js | 77 +++++++++------ .../policy_configuration.js | 27 ++++++ .../policy_selection/policy_selection.js | 40 +++----- .../wizard/components/review/review.js | 9 +- .../public/sections/wizard/wizard.js | 38 +++++--- .../public/store/actions/nodes.js | 31 +++++- .../public/store/reducers/nodes.js | 16 +++- .../public/store/selectors/nodes.js | 19 ++-- .../server/routes/api/nodes/constants.js | 11 +++ .../api/nodes/register_details_route.js | 65 +++++++++++++ .../routes/api/nodes/register_list_route.js | 9 +- .../routes/api/nodes/register_nodes_routes.js | 2 + 19 files changed, 460 insertions(+), 147 deletions(-) create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/index.js create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/node_attrs_details.container.js create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/node_attrs_details.js create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/constants.js create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.js 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 02018804fa462..1ce9bdb957c40 100644 --- a/x-pack/plugins/index_lifecycle_management/public/api/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/api/index.js @@ -16,6 +16,11 @@ export async function loadNodes() { return response.data; } +export async function loadNodeDetails(selectedNodeAttrs) { + const response = await httpClient.get(`${apiPrefix}/nodes/${selectedNodeAttrs}/details`); + return response.data; +} + export async function loadIndexTemplates() { const response = await httpClient.get(`${apiPrefix}/templates`); return response.data; 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 38d600622a8d4..39d260b05301e 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,15 +5,18 @@ */ export const hasErrors = (object, keysToIgnore = []) => { - const errors = []; + let errors = false; 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); + errors = true; + break; } else if (value) { - return hasErrors(value, keysToIgnore); + errors = hasErrors(value, keysToIgnore); + if (errors) { + break; + } } } - return false; + return errors; }; 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 index a88ef8e7a97ee..7acd83c378a41 100644 --- 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 @@ -4,10 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ - - - -import React, { PureComponent } from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { @@ -18,17 +15,20 @@ import { EuiSelect, EuiFieldNumber, EuiHorizontalRule, - EuiCallOut + EuiCallOut, + EuiFormRow, + EuiButtonEmpty, } from '@elastic/eui'; import { STRUCTURE_NODE_ATTRS, STRUCTURE_PRIMARY_NODES, - STRUCTURE_REPLICAS + STRUCTURE_REPLICAS, } from '../../../../../../store/constants'; import { ErrableFormRow } from '../../../../form_errors'; +import { NodeAttrsDetails } from '../../../node_attrs_details'; -export class Configuration extends PureComponent { +export class Configuration extends Component { static propTypes = { fetchNodes: PropTypes.func.isRequired, setSelectedNodeAttrs: PropTypes.func.isRequired, @@ -38,19 +38,27 @@ export class Configuration extends PureComponent { selectedPrimaryShardCount: PropTypes.oneOfType([ PropTypes.number, - PropTypes.string + PropTypes.string, ]).isRequired, selectedNodeAttrs: PropTypes.string.isRequired, nodeOptions: PropTypes.array.isRequired, selectedReplicaCount: PropTypes.oneOfType([ PropTypes.number, - PropTypes.string + PropTypes.string, ]).isRequired, isShowingErrors: PropTypes.bool.isRequired, errors: PropTypes.object.isRequired, - isPrimaryShardCountHigherThanSelectedNodeAttrsCount: PropTypes.bool.isRequired, + isPrimaryShardCountHigherThanSelectedNodeAttrsCount: + PropTypes.bool.isRequired, }; + constructor(props) { + super(props); + this.state = { + isShowingNodeDetailsFlyout: false, + }; + } + componentWillMount() { this.props.fetchNodes(); } @@ -68,7 +76,7 @@ export class Configuration extends PureComponent { selectedNodeAttrs, errors, isShowingErrors, - isPrimaryShardCountHigherThanSelectedNodeAttrsCount + isPrimaryShardCountHigherThanSelectedNodeAttrsCount, } = this.props; const primaryNodeErrors = isPrimaryShardCountHigherThanSelectedNodeAttrsCount ? ( @@ -78,7 +86,8 @@ export class Configuration extends PureComponent { color="warning" iconType="help" > - The selected primary shard count is higher than the number of nodes matching the selected attributes. + The selected primary shard count is higher than the number of nodes + matching the selected attributes. ) : null; @@ -89,29 +98,42 @@ export class Configuration extends PureComponent {

      Configure options

      - - { - await setSelectedNodeAttrs(e.target.value); - validate(); - }} - options={nodeOptions} - /> - + + + + { + await setSelectedNodeAttrs(e.target.value); + validate(); + }} + options={nodeOptions} + /> + + + {selectedNodeAttrs ? ( + + + + this.setState({ isShowingNodeDetailsFlyout: true }) + } + > + See more details about these nodes + + + + ) : null} + - -

      - Optimize these values for throughput. (Add more) -

      + +

      Optimize these values for throughput. (Add more)

      @@ -148,6 +170,12 @@ export class Configuration extends PureComponent { + {this.state.isShowingNodeDetailsFlyout ? ( + this.setState({ isShowingNodeDetailsFlyout: false })} + /> + ) : null} {primaryNodeErrors}
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 new file mode 100644 index 0000000000000..885e965c46c4b --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/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/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 new file mode 100644 index 0000000000000..8887b13740e04 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/node_attrs_details.container.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 { connect } from 'react-redux'; +import { NodeAttrsDetails as PresentationComponent } from './node_attrs_details'; +import { getNodeDetails } from '../../../../store/selectors'; +import { fetchNodeDetails } from '../../../../store/actions'; + +export const NodeAttrsDetails = connect( + (state, ownProps) => ({ + details: getNodeDetails(state, ownProps.selectedNodeAttrs), + }), + { 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 new file mode 100644 index 0000000000000..0af37a84918a8 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/node_attrs_details/node_attrs_details.js @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under 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 { + EuiFlyoutBody, + EuiFlyoutFooter, + EuiFlyout, + EuiTitle, + EuiInMemoryTable, + EuiSpacer, + EuiButtonEmpty, + EuiCallOut, +} 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, + }; + + componentWillMount() { + this.props.fetchNodeDetails(this.props.selectedNodeAttrs); + } + + render() { + const { selectedNodeAttrs, details, close } = this.props; + + return ( + + + +

+ Below is a list of nodes that contain the attribute: `{ + selectedNodeAttrs + }` +

+
+ + + Be aware that the nodes listed here only directly match the node + attribute string and other nodes might be affected by this policy + due to other allocation rules. + + + +
+ + + Close + + +
+ ); + } +} 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 index 7436558c68f46..392783c8587dd 100644 --- 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 @@ -40,6 +40,7 @@ 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, @@ -70,6 +71,7 @@ export class ColdPhase extends PureComponent { const { setPhaseData, validate, + showNodeDetailsFlyout, phaseData, nodeOptions, @@ -170,21 +172,37 @@ export class ColdPhase extends PureComponent { - - { - await setPhaseData(PHASE_NODE_ATTRS, e.target.value); - validate(); - }} - /> - + + + + { + await setPhaseData(PHASE_NODE_ATTRS, e.target.value); + validate(); + }} + /> + + + {phaseData[PHASE_NODE_ATTRS] ? ( + + + showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])} + > + See more details about these nodes + + + + ) : null} + 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 index dfd70d0876767..4ddab994b65d7 100644 --- 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 @@ -4,9 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ - - - import React, { Component } from 'react'; import PropTypes from 'prop-types'; @@ -35,7 +32,7 @@ import { PHASE_PRIMARY_SHARD_COUNT, PHASE_REPLICA_COUNT, PHASE_ROLLOVER_AFTER, - PHASE_ROLLOVER_AFTER_UNITS + PHASE_ROLLOVER_AFTER_UNITS, } from '../../../../../../store/constants'; import { ErrableFormRow } from '../../../../form_errors'; @@ -43,6 +40,7 @@ export class WarmPhase extends Component { static propTypes = { setPhaseData: PropTypes.func.isRequired, validate: PropTypes.func.isRequired, + showNodeDetailsFlyout: PropTypes.func.isRequired, isShowingErrors: PropTypes.bool.isRequired, errors: PropTypes.object.isRequired, @@ -53,40 +51,40 @@ export class WarmPhase extends Component { [PHASE_FORCE_MERGE_ENABLED]: PropTypes.bool.isRequired, [PHASE_FORCE_MERGE_SEGMENTS]: PropTypes.oneOfType([ PropTypes.number, - PropTypes.string + PropTypes.string, ]).isRequired, [PHASE_NODE_ATTRS]: PropTypes.string.isRequired, [PHASE_PRIMARY_SHARD_COUNT]: PropTypes.oneOfType([ PropTypes.number, - PropTypes.string + PropTypes.string, ]).isRequired, [PHASE_REPLICA_COUNT]: PropTypes.oneOfType([ PropTypes.number, - PropTypes.string + PropTypes.string, ]).isRequired, [PHASE_ROLLOVER_AFTER]: PropTypes.oneOfType([ PropTypes.number, - PropTypes.string + PropTypes.string, ]).isRequired, - [PHASE_ROLLOVER_AFTER_UNITS]: PropTypes.string.isRequired + [PHASE_ROLLOVER_AFTER_UNITS]: PropTypes.string.isRequired, }).isRequired, hotPhaseReplicaCount: PropTypes.oneOfType([ PropTypes.number, - PropTypes.string + PropTypes.string, ]).isRequired, hotPhasePrimaryShardCount: PropTypes.oneOfType([ PropTypes.number, - PropTypes.string + PropTypes.string, ]).isRequired, - nodeOptions: PropTypes.array.isRequired + nodeOptions: PropTypes.array.isRequired, }; constructor(props) { super(props); this.state = { - applyOnRollover: false + applyOnRollover: false, }; } @@ -98,6 +96,7 @@ export class WarmPhase extends Component { const { validate, setPhaseData, + showNodeDetailsFlyout, phaseData, hotPhaseReplicaCount, @@ -105,7 +104,7 @@ export class WarmPhase extends Component { nodeOptions, errors, isShowingErrors, - hotPhaseRolloverEnabled + hotPhaseRolloverEnabled, } = this.props; return ( @@ -122,7 +121,7 @@ export class WarmPhase extends Component { width: 64, lineHeight: '64px', textAlign: 'center', - color: 'white' + color: 'white', }} > @@ -213,7 +212,7 @@ export class WarmPhase extends Component { }} options={[ { value: 'd', text: 'days' }, - { value: 'h', text: 'hours' } + { value: 'h', text: 'hours' }, ]} /> @@ -223,21 +222,37 @@ export class WarmPhase extends Component { - - { - await setPhaseData(PHASE_NODE_ATTRS, e.target.value); - validate(); - }} - /> - + + + + { + await setPhaseData(PHASE_NODE_ATTRS, e.target.value); + validate(); + }} + /> + + + {phaseData[PHASE_NODE_ATTRS] ? ( + + + showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])} + > + See more details about these nodes + + + + ) : null} + { + this.setState({ isShowingNodeDetailsFlyout: true, selectedNodeAttrsForDetails }); + } + render() { const { setSelectedPolicyName, @@ -82,6 +91,7 @@ export class PolicyConfiguration extends Component { setIndexName, setAliasName, validate, + back, affectedIndexTemplates, selectedIndexTemplateName, @@ -141,12 +151,14 @@ export class PolicyConfiguration extends Component { @@ -240,6 +252,14 @@ export class PolicyConfiguration extends Component { + + Back + +    Next + + {this.state.isShowingNodeDetailsFlyout ? ( + this.setState({ isShowingNodeDetailsFlyout: false })} + /> + ) : null} ); } 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 index 52fe3a6cb1806..73cd4b58228c1 100644 --- 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 @@ -18,7 +18,9 @@ import { EuiTitle, EuiSpacer, EuiPanel, - EuiText + EuiText, + EuiHorizontalRule, + EuiButtonEmpty } from '@elastic/eui'; export class PolicySelection extends Component { @@ -26,6 +28,7 @@ export class PolicySelection extends Component { fetchPolicies: PropTypes.func.isRequired, setSelectedPolicy: PropTypes.func.isRequired, done: PropTypes.func.isRequired, + back: PropTypes.func.isRequired, existingPolicyName: PropTypes.string.isRequired, policies: PropTypes.array.isRequired @@ -41,7 +44,7 @@ export class PolicySelection extends Component { } render() { - const { policies, existingPolicyName } = this.props; + const { policies, existingPolicyName, back } = this.props; return (
@@ -57,30 +60,6 @@ export class PolicySelection extends Component {

- {/* - - - - Hot - - - - - Warm - - - - - Cold - - - - - Delete - - - - */} @@ -111,6 +90,15 @@ export class PolicySelection extends Component { ))} + + + + Back +
); } 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 aa74c7398b907..c1273f5175210 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 @@ -24,6 +24,7 @@ import { EuiFlexGrid, EuiPanel, EuiText, + EuiButtonEmpty } from '@elastic/eui'; import { getAffectedIndices } from '../../../../api'; @@ -32,6 +33,7 @@ export class Review extends Component { setSelectedPolicyName: PropTypes.func.isRequired, setSaveAsNewPolicy: PropTypes.func.isRequired, done: PropTypes.func.isRequired, + back: PropTypes.func.isRequired, selectedIndexTemplateName: PropTypes.string.isRequired, affectedIndexTemplates: PropTypes.array.isRequired, @@ -63,6 +65,7 @@ export class Review extends Component { render() { const { done, + back, selectedIndexTemplateName, affectedIndexTemplates, @@ -132,7 +135,6 @@ export class Review extends Component { ) : null} - {templateDiff.hasChanged ? ( @@ -161,7 +163,10 @@ export class Review extends Component { ) : null} - + + Back + +    { this.setState({ - selectedStep + selectedStep, }); }; @@ -101,17 +98,28 @@ export class Wizard extends Component { /> ); case 2: - return this.onSelectedStepChanged(3)} />; + return ( + this.onSelectedStepChanged(3)} + back={() => this.onSelectedStepChanged(1)} + /> + ); case 3: return ( this.onSelectedStepChanged(4)} + back={() => this.onSelectedStepChanged(2)} /> ); case 4: - return ; + return ( + this.onSelectedStepChanged(3)} + /> + ); } } @@ -121,29 +129,29 @@ export class Wizard extends Component { title: 'Select a template', isSelected: this.state.selectedStep === 1, isComplete: this.state.selectedStep > 1, - onClick: () => this.onSelectedStepChanged(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) + 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) + 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) - } + onClick: () => this.onSelectedStepChanged(4), + }, ]; return ( 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 index 11b0a77be8106..e357b6d6587f3 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js @@ -6,20 +6,41 @@ import { createAction } from 'redux-actions'; import { toastNotifications } from 'ui/notify'; -import { loadNodes } from '../../api'; +import { loadNodes, loadNodeDetails } 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 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) { + } catch (err) { return toastNotifications.addDanger(err.data.message); } dispatch(fetchedNodes(nodes)); }; + +export const fetchedNodeDetails = createAction( + 'FETCHED_NODE_DETAILS', + (selectedNodeAttrs, details) => ({ + selectedNodeAttrs, + details, + }) +); +export const fetchNodeDetails = selectedNodeAttrs => async dispatch => { + let details; + try { + details = await loadNodeDetails(selectedNodeAttrs); + } catch (err) { + return toastNotifications.addDanger(err.data.message); + } + + dispatch(fetchedNodeDetails(selectedNodeAttrs, details)); +}; 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 index 88d5b9a0f6d53..a5a372ed17a8a 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/reducers/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/reducers/nodes.js @@ -9,7 +9,8 @@ import { fetchedNodes, setSelectedNodeAttrs, setSelectedPrimaryShardCount, - setSelectedReplicaCount + setSelectedReplicaCount, + fetchedNodeDetails } from '../actions/nodes'; const defaultState = { @@ -17,7 +18,8 @@ const defaultState = { selectedNodeAttrs: '', selectedPrimaryShardCount: 1, selectedReplicaCount: 1, - nodes: [] + nodes: [], + details: {}, }; export const nodes = handleActions( @@ -29,6 +31,16 @@ export const nodes = handleActions( nodes }; }, + [fetchedNodeDetails](state, { payload }) { + const { selectedNodeAttrs, details } = payload; + return { + ...state, + details: { + ...state.details, + [selectedNodeAttrs]: details, + } + }; + }, [setSelectedNodeAttrs](state, { payload: selectedNodeAttrs }) { return { ...state, 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 index 1ad1e11e57045..ca0d06f9f2dde 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/nodes.js @@ -4,23 +4,18 @@ * 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), - ], + [state => getNodes(state)], nodes => { if (!nodes) { return []; } const options = Object.keys(nodes).map(attrs => ({ - text: attrs, + text: `${attrs} (${nodes[attrs].length})`, value: attrs, })); @@ -34,8 +29,10 @@ export const getNodeOptions = createSelector( } ); -export const getSelectedPrimaryShardCount = state => state.nodes.selectedPrimaryShardCount; -export const getSelectedReplicaCount = state => state.nodes.selectedReplicaCount; +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)]; @@ -44,3 +41,7 @@ export const getNodesFromSelectedNodeAttrs = state => { } return null; }; + +export const getNodeDetails = (state, selectedNodeAttrs) => { + return state.nodes.details[selectedNodeAttrs]; +}; diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/constants.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/constants.js new file mode 100644 index 0000000000000..d6a9dd774e206 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/constants.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. + */ + +export const NODE_ATTRS_KEYS_TO_IGNORE = [ + 'ml.enabled', + 'ml.machine_memory', + 'ml.max_open_jobs' +]; 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 new file mode 100644 index 0000000000000..9ab30dd0f2f7e --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_details_route.js @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + + + + +import { 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, nodeAttrs) { + return Object.entries(stats.nodes).reduce((accum, [nodeId, stats]) => { + const attributes = stats.attributes || {}; + for (const [key, value] of Object.entries(attributes)) { + if (`${key}:${value}` === nodeAttrs) { + accum.push({ + nodeId, + stats, + }); + break; + } + } + return accum; + }, []); +} + +async function fetchNodeStats(callWithRequest) { + const params = { + format: 'json' + }; + + return await callWithRequest('nodes.stats', params); +} + +export function registerDetailsRoute(server) { + const isEsError = isEsErrorFactory(server); + const licensePreRouting = licensePreRoutingFactory(server); + + server.route({ + path: '/api/index_lifecycle_management/nodes/{nodeAttrs}/details', + method: 'GET', + handler: async (request, reply) => { + const callWithRequest = callWithRequestFactory(server, request); + + try { + const stats = await fetchNodeStats(callWithRequest); + const response = formatStats(stats, request.params.nodeAttrs); + 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_list_route.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/nodes/register_list_route.js index 9320030ba41ed..7b82619665412 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 @@ -11,14 +11,17 @@ 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 { NODE_ATTRS_KEYS_TO_IGNORE } from './constants'; 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); + if (!NODE_ATTRS_KEYS_TO_IGNORE.includes(key)) { + const attributeString = `${key}:${value}`; + accum[attributeString] = accum[attributeString] || []; + accum[attributeString].push(nodeId); + } } return accum; }, {}); 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 index 2ce0bdbe77c44..341f1d4f1ebf3 100644 --- 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 @@ -5,7 +5,9 @@ */ import { registerListRoute } from './register_list_route'; +import { registerDetailsRoute } from './register_details_route'; export function registerNodesRoutes(server) { registerListRoute(server); + registerDetailsRoute(server); } From 0eface25e8f04bbb42bdd901672813adafe10d81 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Fri, 4 May 2018 13:36:14 -0400 Subject: [PATCH 05/62] New diff tool --- .../public/lib/diff_ace_addons.js | 119 + .../public/lib/diff_tools.js | 85 + .../wizard/components/review/diff_view.js | 63 + .../wizard/components/review/review.js | 10 +- .../wizard/components/review/review.less | 10 +- .../public/sections/wizard/diff.json | 2879 +++++++++++++++++ .../public/sections/wizard/wizard.js | 7 + 7 files changed, 3166 insertions(+), 7 deletions(-) create mode 100644 x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js create mode 100644 x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/diff_view.js create mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js b/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js new file mode 100644 index 0000000000000..5e34f8f2e436a --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under 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 ace from 'brace'; +import { ADDITION_PREFIX, REMOVAL_PREFIX } from './diff_tools'; + +function findInObject(key, obj) { + const objKeys = Object.keys(obj); + for (const objKey of objKeys) { + if (objKey === key) { + return obj[objKey]; + } + if (typeof obj[objKey] === 'object' && !Array.isArray(obj[objKey])) { + const item = findInObject(key, obj[objKey]); + if (item !== false) { + return item; + } + } + } + return false; +} + +function getDiffClasses(key, val, jsonObject) { + // const debug = false;//key === 'sattr_name'; + + let value = val; + if (value.endsWith(',')) { + value = value.slice(0, -1); + } + if (value.startsWith('"')) { + value = value.slice(1, -1); + } + + const additionValue = findInObject(`${ADDITION_PREFIX}${key}`, jsonObject); + const removalValue = findInObject(`${REMOVAL_PREFIX}${key}`, jsonObject); + + const isAddition = Array.isArray(additionValue) + ? !!additionValue.find(v => v === value) + : additionValue === value; + const isRemoval = Array.isArray(removalValue) + ? !!removalValue.find(v => v === value) + : removalValue === value; + + let diffClasses = ''; + if (isAddition) { + diffClasses = 'diff_addition ace_variable'; + } else if (isRemoval) { + diffClasses = 'diff_removal ace_variable'; + } else { + diffClasses = 'variable'; + } + + // debug && console.log(`getDiffClasses() + // key='${key}' + // value='${value}' + // additionValue='${additionValue}' + // removalValue='${removalValue}' + // isAddition=${isAddition} + // isRemoval=${isRemoval} + // diffClasses='${diffClasses}' + // `); + + return diffClasses; +} + +export const addDiffAddonsForAce = jsonObject => { + const JsonHighlightRules = ace.acequire('ace/mode/json_highlight_rules') + .JsonHighlightRules; + class DiffJsonHighlightRules extends JsonHighlightRules { + constructor(props) { + super(props); + this.$rules = new JsonHighlightRules().getRules(); + + let currentArrayKey; + this.addRules({ + start: [ + { + token: (key, val) => { + return getDiffClasses(key, val, jsonObject); + }, + regex: '(?:"([\\w-+]+)"\\s*:\\s*([^\\n\\[]+)$)', + }, + { + token: key => { + currentArrayKey = key; + return 'variable'; + }, + next: 'array', + regex: '(?:"([\\w-+]+)"\\s*:\\s*\\[$)', + }, + ...this.$rules.start, + ], + array: [ + { + token: val => { + return getDiffClasses(currentArrayKey, val, jsonObject); + }, + next: 'start', + regex: '\\s*"([^"]+)"\\s*', + }, + ], + }); + } + } + + const JsonMode = ace.acequire('ace/mode/json').Mode; + class DiffJsonMode extends JsonMode { + constructor(props) { + super(props); + this.HighlightRules = DiffJsonHighlightRules; + } + } + + ace.define('ace/mode/diff_json', [], () => ({ + Mode: DiffJsonMode, + })); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js b/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js new file mode 100644 index 0000000000000..03dc6bf91014d --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.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. + */ + +export const ADDITION_PREFIX = '$'; +export const REMOVAL_PREFIX = '^'; +const removePrefixRegex = new RegExp( + `(\\${ADDITION_PREFIX}|\\${REMOVAL_PREFIX})`, + 'g' +); + +const isObject = value => typeof value === 'object' && !Array.isArray(value); +const isDifferent = (obj, key, value) => { + // If the object does not contain the key, then ignore since it's not a removal or addition + if (!obj.hasOwnProperty(key)) { + return false; + } + + // If we're dealing with an array, we need something better than a simple === comparison + if (Array.isArray(value)) { + return JSON.stringify(value) !== JSON.stringify(obj[key]); + } + + // If the value is an object, do not try and compare as this is called in a recursive function + // so safely ignore + if (typeof value === 'object') { + return false; + } + + // We should be dealing with primitives so do a basic comparison + return obj[key] !== value; +}; +const getAdditions = obj => { + const result = {}; + for (const [key, value] of Object.entries(obj)) { + if (isObject(value)) { + result[`${ADDITION_PREFIX}${key}`] = getAdditions(value); + } else { + result[`${ADDITION_PREFIX}${key}`] = value; + } + } + return result; +}; + +export const removePrefixes = str => str.replace(removePrefixRegex, ''); + +export const mergeAndPreserveDuplicateKeys = (source, target, result = {}) => { + for (const [key, value] of Object.entries(source)) { + // const debug = key === 'fooobar'; + // debug && console.log('mergeAndPreserveDuplicateKeys', key, value, target); + if (isDifferent(target, key, value)) { + // debug && console.log('isDifferent'); + result[`${REMOVAL_PREFIX}${key}`] = value; + result[`${ADDITION_PREFIX}${key}`] = target[key]; + } else if (isObject(value)) { + // debug && console.log('value is object', target[key]); + if (target.hasOwnProperty(key)) { + result[key] = mergeAndPreserveDuplicateKeys(value, target[key]); + } else { + result[key] = value; + } + } else { + result[key] = value; + } + } + + for (const [key, value] of Object.entries(target)) { + if ( + result.hasOwnProperty(key) || + result.hasOwnProperty(`${REMOVAL_PREFIX}${key}`) || + result.hasOwnProperty(`${ADDITION_PREFIX}${key}`) + ) { + continue; + } + + if (isObject(value)) { + result[`${ADDITION_PREFIX}${key}`] = getAdditions(value); + } else { + result[`${ADDITION_PREFIX}${key}`] = value; + } + } + return result; +}; 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 new file mode 100644 index 0000000000000..f76022a06359a --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/review/diff_view.js @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import React, { PureComponent } from 'react'; +import PropTypes from 'prop-types'; + +import { EuiCodeEditor } from '@elastic/eui'; + +import 'brace/mode/json'; +import { + mergeAndPreserveDuplicateKeys, + removePrefixes, +} from '../../../../lib/diff_tools'; +import { addDiffAddonsForAce } from '../../../../lib/diff_ace_addons'; + +export class DiffView extends PureComponent { + static propTypes = { + templateDiff: PropTypes.shape({ + originalFullIndexTemplate: PropTypes.object.isRequired, + newFullIndexTemplate: PropTypes.object.isRequired, + }).isRequired, + }; + + render() { + const { + templateDiff: { originalFullIndexTemplate, newFullIndexTemplate }, + } = this.props; + + // console.log(JSON.stringify(this.props)); + + const mergedJson = mergeAndPreserveDuplicateKeys( + originalFullIndexTemplate, + newFullIndexTemplate + ); + + // console.log('mergedJson', mergedJson); + + // Strip the ^ and $ characters + const mergedJsonAsString = removePrefixes( + JSON.stringify(mergedJson, null, 2) + ); + + addDiffAddonsForAce(mergedJson); + + return ( + + ); + } +} 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 c1273f5175210..66c54a738142f 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 @@ -7,7 +7,7 @@ import React, { Fragment, Component } from 'react'; import PropTypes from 'prop-types'; -import DiffEditor from 'react-ace/lib/diff'; +// import DiffEditor from 'react-ace/lib/diff'; import './review.less'; import 'brace/theme/github'; @@ -27,6 +27,7 @@ import { EuiButtonEmpty } from '@elastic/eui'; import { getAffectedIndices } from '../../../../api'; +import { DiffView } from './diff_view'; export class Review extends Component { static propTypes = { @@ -145,7 +146,10 @@ export class Review extends Component { - + {/* + /> */} 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 index 862b1bd58e8c8..e826e78a7bf7e 100644 --- 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 @@ -1,5 +1,7 @@ -.codeMarker { - background: #FFF677; - position:absolute; - z-index:20 +.ace_diff_addition { + background-color: #e6ffed; +} + +.ace_diff_removal { + background-color: #ffeef0; } diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json new file mode 100644 index 0000000000000..f7e2243cbddea --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json @@ -0,0 +1,2879 @@ +{ + "originalFullIndexTemplate": { + "order": 1, + "index_patterns": ["filebeat-7.0.0-alpha1-*"], + "settings": { + "index": { + "lifecycle": { + "name": "my_policy4" + }, + "routing": { + "allocation": { + "include": { + "sattr_name": "lala" + } + } + }, + "mapping": { + "total_fields": { + "limit": "10000" + } + }, + "refresh_interval": "5s", + "number_of_shards": "3", + "number_of_routing_shards": "30", + "number_of_replicas": "0" + } + }, + "mappings": { + "doc": { + "dynamic_templates": [{ + "fields": { + "mapping": { + "type": "keyword" + }, + "match_mapping_type": "string", + "path_match": "fields.*" + } + }, { + "docker.container.labels": { + "mapping": { + "type": "keyword" + }, + "match_mapping_type": "string", + "path_match": "docker.container.labels.*" + } + }, { + "strings_as_keyword": { + "mapping": { + "ignore_above": 1024, + "type": "keyword" + }, + "match_mapping_type": "string" + } + }], + "properties": { + "tags": { + "type": "keyword", + "ignore_above": 1024 + }, + "error": { + "properties": { + "code": { + "type": "long" + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + } + } + }, + "message": { + "type": "text", + "norms": false + }, + "read_timestamp": { + "type": "keyword", + "ignore_above": 1024 + }, + "apache2": { + "properties": { + "access": { + "properties": { + "http_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "response_code": { + "type": "long" + }, + "user_agent": { + "properties": { + "os": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "minor": { + "type": "long" + }, + "major": { + "type": "long" + }, + "patch": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_major": { + "type": "long" + }, + "os_minor": { + "type": "long" + }, + "device": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "geoip": { + "properties": { + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "remote_ip": { + "ignore_above": 1024, + "type": "keyword" + }, + "user_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "method": { + "type": "keyword", + "ignore_above": 1024 + }, + "agent": { + "type": "text", + "norms": false + }, + "url": { + "type": "keyword", + "ignore_above": 1024 + }, + "body_sent": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "referrer": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "error": { + "properties": { + "client": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + }, + "pid": { + "type": "long" + }, + "tid": { + "type": "long" + }, + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "icinga": { + "properties": { + "main": { + "properties": { + "facility": { + "type": "keyword", + "ignore_above": 1024 + }, + "severity": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "norms": false, + "type": "text" + } + } + }, + "startup": { + "properties": { + "facility": { + "type": "keyword", + "ignore_above": 1024 + }, + "severity": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "norms": false, + "type": "text" + } + } + }, + "debug": { + "properties": { + "message": { + "type": "text", + "norms": false + }, + "facility": { + "ignore_above": 1024, + "type": "keyword" + }, + "severity": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "logstash": { + "properties": { + "log": { + "properties": { + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "module": { + "type": "keyword", + "ignore_above": 1024 + }, + "thread": { + "type": "text", + "norms": false + }, + "log_event": { + "type": "object" + }, + "message": { + "type": "text", + "norms": false + } + } + }, + "slowlog": { + "properties": { + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "event": { + "type": "text", + "norms": false + }, + "plugin_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "took_in_nanos": { + "type": "long" + }, + "plugin_params": { + "type": "text", + "norms": false + }, + "plugin_params_object": { + "type": "object" + }, + "message": { + "norms": false, + "type": "text" + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "thread": { + "type": "text", + "norms": false + }, + "plugin_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "took_in_millis": { + "type": "long" + } + } + } + } + }, + "mysql": { + "properties": { + "slowlog": { + "properties": { + "rows_sent": { + "type": "long" + }, + "id": { + "type": "long" + }, + "rows_examined": { + "type": "long" + }, + "timestamp": { + "type": "long" + }, + "query": { + "type": "keyword", + "ignore_above": 1024 + }, + "user": { + "type": "keyword", + "ignore_above": 1024 + }, + "host": { + "type": "keyword", + "ignore_above": 1024 + }, + "ip": { + "ignore_above": 1024, + "type": "keyword" + }, + "query_time": { + "properties": { + "sec": { + "type": "float" + } + } + }, + "lock_time": { + "properties": { + "sec": { + "type": "float" + } + } + } + } + }, + "error": { + "properties": { + "thread_id": { + "type": "long" + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + }, + "timestamp": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "beat": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "hostname": { + "type": "keyword", + "ignore_above": 1024 + }, + "timezone": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "docker": { + "properties": { + "container": { + "properties": { + "image": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "labels": { + "type": "object" + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "fileset": { + "properties": { + "module": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "@timestamp": { + "type": "date" + }, + "meta": { + "properties": { + "cloud": { + "properties": { + "provider": { + "type": "keyword", + "ignore_above": 1024 + }, + "instance_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "instance_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "machine_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "project_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "region": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "kafka": { + "properties": { + "log": { + "properties": { + "trace": { + "properties": { + "class": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + }, + "full": { + "type": "text", + "norms": false + } + } + }, + "timestamp": { + "type": "keyword", + "ignore_above": 1024 + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + }, + "component": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "type": "text", + "norms": false + } + } + } + } + }, + "redis": { + "properties": { + "slowlog": { + "properties": { + "id": { + "type": "long" + }, + "key": { + "type": "keyword", + "ignore_above": 1024 + }, + "args": { + "type": "keyword", + "ignore_above": 1024 + }, + "cmd": { + "type": "keyword", + "ignore_above": 1024 + }, + "duration": { + "properties": { + "us": { + "type": "long" + } + } + } + } + }, + "log": { + "properties": { + "pid": { + "type": "long" + }, + "role": { + "type": "keyword", + "ignore_above": 1024 + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + } + } + } + } + }, + "input": { + "properties": { + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "iis": { + "properties": { + "access": { + "properties": { + "server_ip": { + "type": "keyword", + "ignore_above": 1024 + }, + "port": { + "type": "long" + }, + "user_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "response_code": { + "type": "long" + }, + "server_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "cookie": { + "type": "keyword", + "ignore_above": 1024 + }, + "method": { + "type": "keyword", + "ignore_above": 1024 + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + }, + "win32_status": { + "type": "long" + }, + "agent": { + "type": "text", + "norms": false + }, + "user_agent": { + "properties": { + "major": { + "type": "long" + }, + "patch": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "os": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_minor": { + "type": "long" + }, + "device": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_major": { + "type": "long" + }, + "os_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "minor": { + "type": "long" + } + } + }, + "query_string": { + "ignore_above": 1024, + "type": "keyword" + }, + "referrer": { + "type": "keyword", + "ignore_above": 1024 + }, + "sub_status": { + "type": "long" + }, + "request_time_ms": { + "type": "long" + }, + "http_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "hostname": { + "type": "keyword", + "ignore_above": 1024 + }, + "body_sent": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "geoip": { + "properties": { + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "remote_ip": { + "type": "keyword", + "ignore_above": 1024 + }, + "site_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "body_received": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "error": { + "properties": { + "remote_port": { + "type": "long" + }, + "server_port": { + "type": "long" + }, + "response_code": { + "type": "long" + }, + "reason_phrase": { + "type": "keyword", + "ignore_above": 1024 + }, + "queue_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "remote_ip": { + "type": "keyword", + "ignore_above": 1024 + }, + "http_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "method": { + "type": "keyword", + "ignore_above": 1024 + }, + "url": { + "type": "keyword", + "ignore_above": 1024 + }, + "geoip": { + "properties": { + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "server_ip": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "fields": { + "type": "object" + }, + "kubernetes": { + "properties": { + "container": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "image": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "pod": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "namespace": { + "type": "keyword", + "ignore_above": 1024 + }, + "node": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "labels": { + "type": "object" + }, + "annotations": { + "type": "object" + } + } + }, + "source": { + "type": "keyword", + "ignore_above": 1024 + }, + "auditd": { + "properties": { + "log": { + "properties": { + "geoip": { + "properties": { + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + } + } + }, + "old_ses": { + "type": "keyword", + "ignore_above": 1024 + }, + "new_ses": { + "type": "keyword", + "ignore_above": 1024 + }, + "res": { + "type": "keyword", + "ignore_above": 1024 + }, + "sequence": { + "type": "long" + }, + "item": { + "type": "keyword", + "ignore_above": 1024 + }, + "items": { + "type": "keyword", + "ignore_above": 1024 + }, + "record_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "old_auid": { + "ignore_above": 1024, + "type": "keyword" + }, + "ppid": { + "type": "keyword", + "ignore_above": 1024 + }, + "a0": { + "type": "keyword", + "ignore_above": 1024 + }, + "new_auid": { + "type": "keyword", + "ignore_above": 1024 + }, + "acct": { + "type": "keyword", + "ignore_above": 1024 + }, + "pid": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "nginx": { + "properties": { + "access": { + "properties": { + "remote_ip": { + "type": "keyword", + "ignore_above": 1024 + }, + "user_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "http_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "user_agent": { + "properties": { + "os_minor": { + "type": "long" + }, + "major": { + "type": "long" + }, + "minor": { + "type": "long" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_major": { + "type": "long" + }, + "device": { + "type": "keyword", + "ignore_above": 1024 + }, + "patch": { + "type": "keyword", + "ignore_above": 1024 + }, + "os": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "referrer": { + "type": "keyword", + "ignore_above": 1024 + }, + "agent": { + "type": "text", + "norms": false + }, + "geoip": { + "properties": { + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "method": { + "type": "keyword", + "ignore_above": 1024 + }, + "url": { + "type": "keyword", + "ignore_above": 1024 + }, + "response_code": { + "type": "long" + }, + "body_sent": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "error": { + "properties": { + "pid": { + "type": "long" + }, + "tid": { + "type": "long" + }, + "connection_id": { + "type": "long" + }, + "message": { + "type": "text", + "norms": false + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "offset": { + "type": "long" + }, + "stream": { + "type": "keyword", + "ignore_above": 1024 + }, + "postgresql": { + "properties": { + "log": { + "properties": { + "timezone": { + "type": "keyword", + "ignore_above": 1024 + }, + "thread_id": { + "type": "long" + }, + "database": { + "type": "keyword", + "ignore_above": 1024 + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + }, + "timestamp": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "type": "keyword", + "ignore_above": 1024 + }, + "duration": { + "type": "float" + }, + "query": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "traefik": { + "properties": { + "access": { + "properties": { + "referrer": { + "type": "keyword", + "ignore_above": 1024 + }, + "geoip": { + "properties": { + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "method": { + "ignore_above": 1024, + "type": "keyword" + }, + "body_sent": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "user_agent": { + "properties": { + "device": { + "type": "keyword", + "ignore_above": 1024 + }, + "minor": { + "type": "long" + }, + "os_minor": { + "type": "long" + }, + "major": { + "type": "long" + }, + "patch": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "os": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_major": { + "type": "long" + }, + "os_name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "frontend_name": { + "type": "text", + "norms": false + }, + "http_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "response_code": { + "type": "long" + }, + "remote_ip": { + "type": "keyword", + "ignore_above": 1024 + }, + "user_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "request_count": { + "type": "long" + }, + "backend_url": { + "type": "text", + "norms": false + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + }, + "agent": { + "type": "text", + "norms": false + } + } + } + } + }, + "prospector": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "osquery": { + "properties": { + "result": { + "properties": { + "host_identifier": { + "type": "keyword", + "ignore_above": 1024 + }, + "unix_time": { + "type": "long" + }, + "calendar_time": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "action": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "system": { + "properties": { + "syslog": { + "properties": { + "program": { + "type": "keyword", + "ignore_above": 1024 + }, + "pid": { + "ignore_above": 1024, + "type": "keyword" + }, + "message": { + "type": "keyword", + "ignore_above": 1024 + }, + "timestamp": { + "type": "keyword", + "ignore_above": 1024 + }, + "hostname": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "auth": { + "properties": { + "groupadd": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "type": "long" + } + } + }, + "hostname": { + "type": "keyword", + "ignore_above": 1024 + }, + "pid": { + "type": "long" + }, + "user": { + "type": "keyword", + "ignore_above": 1024 + }, + "useradd": { + "properties": { + "home": { + "type": "keyword", + "ignore_above": 1024 + }, + "shell": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "uid": { + "type": "long" + }, + "gid": { + "type": "long" + } + } + }, + "sudo": { + "properties": { + "error": { + "type": "keyword", + "ignore_above": 1024 + }, + "tty": { + "ignore_above": 1024, + "type": "keyword" + }, + "pwd": { + "type": "keyword", + "ignore_above": 1024 + }, + "user": { + "type": "keyword", + "ignore_above": 1024 + }, + "command": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "timestamp": { + "type": "keyword", + "ignore_above": 1024 + }, + "program": { + "ignore_above": 1024, + "type": "keyword" + }, + "message": { + "type": "keyword", + "ignore_above": 1024 + }, + "ssh": { + "properties": { + "geoip": { + "properties": { + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + } + } + }, + "event": { + "ignore_above": 1024, + "type": "keyword" + }, + "method": { + "type": "keyword", + "ignore_above": 1024 + }, + "ip": { + "type": "ip" + }, + "dropped_ip": { + "type": "ip" + }, + "port": { + "type": "long" + }, + "signature": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } + } + }, + "_meta": { + "version": "7.0.0-alpha1" + }, + "date_detection": false + } + }, + "aliases": {} + }, + "newFullIndexTemplate": { + "order": 1, + "index_patterns": ["filebeat-7.0.0-alpha1-*"], + "settings": { + "index": { + "lifecycle": { + "name": "my_policy41" + }, + "routing": { + "allocation": { + "include": { + "sattr_name": "warm_node:true" + } + } + }, + "mapping": { + "total_fields": { + "limit": "10000" + } + }, + "refresh_interval": "5s", + "number_of_shards": "3", + "number_of_routing_shards": "30", + "number_of_replicas": "1" + } + }, + "mappings": { + "doc": { + "dynamic_templates": [{ + "fields": { + "mapping": { + "type": "keyword" + }, + "match_mapping_type": "string", + "path_match": "fields.*" + } + }, { + "docker.container.labels": { + "mapping": { + "type": "keyword" + }, + "match_mapping_type": "string", + "path_match": "docker.container.labels.*" + } + }, { + "strings_as_keyword": { + "mapping": { + "ignore_above": 1024, + "type": "keyword" + }, + "match_mapping_type": "string" + } + }], + "properties": { + "tags": { + "type": "keyword", + "ignore_above": 1024 + }, + "error": { + "properties": { + "code": { + "type": "long" + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + } + } + }, + "message": { + "type": "text", + "norms": false + }, + "read_timestamp": { + "type": "keyword", + "ignore_above": 1024 + }, + "apache2": { + "properties": { + "access": { + "properties": { + "http_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "response_code": { + "type": "long" + }, + "user_agent": { + "properties": { + "os": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "minor": { + "type": "long" + }, + "major": { + "type": "long" + }, + "patch": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_major": { + "type": "long" + }, + "os_minor": { + "type": "long" + }, + "device": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "geoip": { + "properties": { + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "remote_ip": { + "ignore_above": 1024, + "type": "keyword" + }, + "user_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "method": { + "type": "keyword", + "ignore_above": 1024 + }, + "agent": { + "type": "text", + "norms": false + }, + "url": { + "type": "keyword", + "ignore_above": 1024 + }, + "body_sent": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "referrer": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "error": { + "properties": { + "client": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + }, + "pid": { + "type": "long" + }, + "tid": { + "type": "long" + }, + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "icinga": { + "properties": { + "main": { + "properties": { + "facility": { + "type": "keyword", + "ignore_above": 1024 + }, + "severity": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "norms": false, + "type": "text" + } + } + }, + "startup": { + "properties": { + "facility": { + "type": "keyword", + "ignore_above": 1024 + }, + "severity": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "norms": false, + "type": "text" + } + } + }, + "debug": { + "properties": { + "message": { + "type": "text", + "norms": false + }, + "facility": { + "ignore_above": 1024, + "type": "keyword" + }, + "severity": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "logstash": { + "properties": { + "log": { + "properties": { + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "module": { + "type": "keyword", + "ignore_above": 1024 + }, + "thread": { + "type": "text", + "norms": false + }, + "log_event": { + "type": "object" + }, + "message": { + "type": "text", + "norms": false + } + } + }, + "slowlog": { + "properties": { + "module": { + "ignore_above": 1024, + "type": "keyword" + }, + "event": { + "type": "text", + "norms": false + }, + "plugin_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "took_in_nanos": { + "type": "long" + }, + "plugin_params": { + "type": "text", + "norms": false + }, + "plugin_params_object": { + "type": "object" + }, + "message": { + "norms": false, + "type": "text" + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "thread": { + "type": "text", + "norms": false + }, + "plugin_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "took_in_millis": { + "type": "long" + } + } + } + } + }, + "mysql": { + "properties": { + "slowlog": { + "properties": { + "rows_sent": { + "type": "long" + }, + "id": { + "type": "long" + }, + "rows_examined": { + "type": "long" + }, + "timestamp": { + "type": "long" + }, + "query": { + "type": "keyword", + "ignore_above": 1024 + }, + "user": { + "type": "keyword", + "ignore_above": 1024 + }, + "host": { + "type": "keyword", + "ignore_above": 1024 + }, + "ip": { + "ignore_above": 1024, + "type": "keyword" + }, + "query_time": { + "properties": { + "sec": { + "type": "float" + } + } + }, + "lock_time": { + "properties": { + "sec": { + "type": "float" + } + } + } + } + }, + "error": { + "properties": { + "thread_id": { + "type": "long" + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + }, + "timestamp": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "beat": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "hostname": { + "type": "keyword", + "ignore_above": 1024 + }, + "timezone": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "docker": { + "properties": { + "container": { + "properties": { + "image": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "labels": { + "type": "object" + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "fileset": { + "properties": { + "module": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "@timestamp": { + "type": "date" + }, + "meta": { + "properties": { + "cloud": { + "properties": { + "provider": { + "type": "keyword", + "ignore_above": 1024 + }, + "instance_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "instance_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "machine_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "availability_zone": { + "ignore_above": 1024, + "type": "keyword" + }, + "project_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "region": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "kafka": { + "properties": { + "log": { + "properties": { + "trace": { + "properties": { + "class": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + }, + "full": { + "type": "text", + "norms": false + } + } + }, + "timestamp": { + "type": "keyword", + "ignore_above": 1024 + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + }, + "component": { + "ignore_above": 1024, + "type": "keyword" + }, + "class": { + "type": "text", + "norms": false + } + } + } + } + }, + "redis": { + "properties": { + "slowlog": { + "properties": { + "id": { + "type": "long" + }, + "key": { + "type": "keyword", + "ignore_above": 1024 + }, + "args": { + "type": "keyword", + "ignore_above": 1024 + }, + "cmd": { + "type": "keyword", + "ignore_above": 1024 + }, + "duration": { + "properties": { + "us": { + "type": "long" + } + } + } + } + }, + "log": { + "properties": { + "pid": { + "type": "long" + }, + "role": { + "type": "keyword", + "ignore_above": 1024 + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + } + } + } + } + }, + "input": { + "properties": { + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "iis": { + "properties": { + "access": { + "properties": { + "server_ip": { + "type": "keyword", + "ignore_above": 1024 + }, + "port": { + "type": "long" + }, + "user_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "response_code": { + "type": "long" + }, + "server_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "cookie": { + "type": "keyword", + "ignore_above": 1024 + }, + "method": { + "type": "keyword", + "ignore_above": 1024 + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + }, + "win32_status": { + "type": "long" + }, + "agent": { + "type": "text", + "norms": false + }, + "user_agent": { + "properties": { + "major": { + "type": "long" + }, + "patch": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "os": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_minor": { + "type": "long" + }, + "device": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_major": { + "type": "long" + }, + "os_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "minor": { + "type": "long" + } + } + }, + "query_string": { + "ignore_above": 1024, + "type": "keyword" + }, + "referrer": { + "type": "keyword", + "ignore_above": 1024 + }, + "sub_status": { + "type": "long" + }, + "request_time_ms": { + "type": "long" + }, + "http_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "hostname": { + "type": "keyword", + "ignore_above": 1024 + }, + "body_sent": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "geoip": { + "properties": { + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "remote_ip": { + "type": "keyword", + "ignore_above": 1024 + }, + "site_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "body_received": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "error": { + "properties": { + "remote_port": { + "type": "long" + }, + "server_port": { + "type": "long" + }, + "response_code": { + "type": "long" + }, + "reason_phrase": { + "type": "keyword", + "ignore_above": 1024 + }, + "queue_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "remote_ip": { + "type": "keyword", + "ignore_above": 1024 + }, + "http_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "method": { + "type": "keyword", + "ignore_above": 1024 + }, + "url": { + "type": "keyword", + "ignore_above": 1024 + }, + "geoip": { + "properties": { + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "server_ip": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "fields": { + "type": "object" + }, + "kubernetes": { + "properties": { + "container": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "image": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "pod": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "namespace": { + "type": "keyword", + "ignore_above": 1024 + }, + "node": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "labels": { + "type": "object" + }, + "annotations": { + "type": "object" + } + } + }, + "source": { + "type": "keyword", + "ignore_above": 1024 + }, + "auditd": { + "properties": { + "log": { + "properties": { + "geoip": { + "properties": { + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "ignore_above": 1024, + "type": "keyword" + }, + "location": { + "type": "geo_point" + } + } + }, + "old_ses": { + "type": "keyword", + "ignore_above": 1024 + }, + "new_ses": { + "type": "keyword", + "ignore_above": 1024 + }, + "res": { + "type": "keyword", + "ignore_above": 1024 + }, + "sequence": { + "type": "long" + }, + "item": { + "type": "keyword", + "ignore_above": 1024 + }, + "items": { + "type": "keyword", + "ignore_above": 1024 + }, + "record_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "old_auid": { + "ignore_above": 1024, + "type": "keyword" + }, + "ppid": { + "type": "keyword", + "ignore_above": 1024 + }, + "a0": { + "type": "keyword", + "ignore_above": 1024 + }, + "new_auid": { + "type": "keyword", + "ignore_above": 1024 + }, + "acct": { + "type": "keyword", + "ignore_above": 1024 + }, + "pid": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "nginx": { + "properties": { + "access": { + "properties": { + "remote_ip": { + "type": "keyword", + "ignore_above": 1024 + }, + "user_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "http_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "user_agent": { + "properties": { + "os_minor": { + "type": "long" + }, + "major": { + "type": "long" + }, + "minor": { + "type": "long" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_major": { + "type": "long" + }, + "device": { + "type": "keyword", + "ignore_above": 1024 + }, + "patch": { + "type": "keyword", + "ignore_above": 1024 + }, + "os": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_name": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "referrer": { + "type": "keyword", + "ignore_above": 1024 + }, + "agent": { + "type": "text", + "norms": false + }, + "geoip": { + "properties": { + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "method": { + "type": "keyword", + "ignore_above": 1024 + }, + "url": { + "type": "keyword", + "ignore_above": 1024 + }, + "response_code": { + "type": "long" + }, + "body_sent": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "error": { + "properties": { + "pid": { + "type": "long" + }, + "tid": { + "type": "long" + }, + "connection_id": { + "type": "long" + }, + "message": { + "type": "text", + "norms": false + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "offset": { + "type": "long" + }, + "stream": { + "type": "keyword", + "ignore_above": 1024 + }, + "postgresql": { + "properties": { + "log": { + "properties": { + "timezone": { + "type": "keyword", + "ignore_above": 1024 + }, + "thread_id": { + "type": "long" + }, + "database": { + "type": "keyword", + "ignore_above": 1024 + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + }, + "timestamp": { + "ignore_above": 1024, + "type": "keyword" + }, + "user": { + "type": "keyword", + "ignore_above": 1024 + }, + "duration": { + "type": "float" + }, + "query": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "traefik": { + "properties": { + "access": { + "properties": { + "referrer": { + "type": "keyword", + "ignore_above": 1024 + }, + "geoip": { + "properties": { + "continent_name": { + "ignore_above": 1024, + "type": "keyword" + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "method": { + "ignore_above": 1024, + "type": "keyword" + }, + "body_sent": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "user_agent": { + "properties": { + "device": { + "type": "keyword", + "ignore_above": 1024 + }, + "minor": { + "type": "long" + }, + "os_minor": { + "type": "long" + }, + "major": { + "type": "long" + }, + "patch": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "os": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_major": { + "type": "long" + }, + "os_name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "frontend_name": { + "type": "text", + "norms": false + }, + "http_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "response_code": { + "type": "long" + }, + "remote_ip": { + "type": "keyword", + "ignore_above": 1024 + }, + "user_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "request_count": { + "type": "long" + }, + "backend_url": { + "type": "text", + "norms": false + }, + "url": { + "ignore_above": 1024, + "type": "keyword" + }, + "agent": { + "type": "text", + "norms": false + } + } + } + } + }, + "prospector": { + "properties": { + "type": { + "ignore_above": 1024, + "type": "keyword" + } + } + }, + "osquery": { + "properties": { + "result": { + "properties": { + "host_identifier": { + "type": "keyword", + "ignore_above": 1024 + }, + "unix_time": { + "type": "long" + }, + "calendar_time": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "action": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "system": { + "properties": { + "syslog": { + "properties": { + "program": { + "type": "keyword", + "ignore_above": 1024 + }, + "pid": { + "ignore_above": 1024, + "type": "keyword" + }, + "message": { + "type": "keyword", + "ignore_above": 1024 + }, + "timestamp": { + "type": "keyword", + "ignore_above": 1024 + }, + "hostname": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "auth": { + "properties": { + "groupadd": { + "properties": { + "name": { + "ignore_above": 1024, + "type": "keyword" + }, + "gid": { + "type": "long" + } + } + }, + "hostname": { + "type": "keyword", + "ignore_above": 1024 + }, + "pid": { + "type": "long" + }, + "user": { + "type": "keyword", + "ignore_above": 1024 + }, + "useradd": { + "properties": { + "home": { + "type": "keyword", + "ignore_above": 1024 + }, + "shell": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "uid": { + "type": "long" + }, + "gid": { + "type": "long" + } + } + }, + "sudo": { + "properties": { + "error": { + "type": "keyword", + "ignore_above": 1024 + }, + "tty": { + "ignore_above": 1024, + "type": "keyword" + }, + "pwd": { + "type": "keyword", + "ignore_above": 1024 + }, + "user": { + "type": "keyword", + "ignore_above": 1024 + }, + "command": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "timestamp": { + "type": "keyword", + "ignore_above": 1024 + }, + "program": { + "ignore_above": 1024, + "type": "keyword" + }, + "message": { + "type": "keyword", + "ignore_above": 1024 + }, + "ssh": { + "properties": { + "geoip": { + "properties": { + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + } + } + }, + "event": { + "ignore_above": 1024, + "type": "keyword" + }, + "method": { + "type": "keyword", + "ignore_above": 1024 + }, + "ip": { + "type": "ip" + }, + "dropped_ip": { + "type": "ip" + }, + "port": { + "type": "long" + }, + "signature": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } + } + }, + "_meta": { + "version": "7.0.0-alpha1" + }, + "date_detection": false + } + }, + "aliases": {} + }, + "hasChanged": true +} 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 index 1e2b4c4ac68c8..9a73050b124ff 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js @@ -24,6 +24,8 @@ import { STRUCTURE_INDEX_TEMPLATE, STRUCTURE_POLICY_CONFIGURATION, } from '../../store/constants'; +// import { DiffView } from './components/review/diff_view'; +// import diff from './diff.json'; export class Wizard extends Component { static propTypes = { @@ -154,6 +156,8 @@ export class Wizard extends Component { }, ]; + // const templateDiff = diff; + return ( @@ -166,6 +170,9 @@ export class Wizard extends Component { + {/* */} {this.renderContent()} ); From 9e5e2c4c47d0b1caf8ec0c16e88aa120227fd3e4 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 7 May 2018 11:04:47 -0400 Subject: [PATCH 06/62] Scroll to change for review diff --- .../public/lib/diff_ace_addons.js | 2 +- .../public/lib/diff_tools.js | 25 +- .../wizard/components/review/diff_view.js | 78 +- .../public/sections/wizard/diff.json | 3149 ++--------------- 4 files changed, 358 insertions(+), 2896 deletions(-) diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js b/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js index 5e34f8f2e436a..f1f3b0a018d94 100644 --- a/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js +++ b/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js @@ -23,7 +23,7 @@ function findInObject(key, obj) { } function getDiffClasses(key, val, jsonObject) { - // const debug = false;//key === 'sattr_name'; + // const debug = key === 'react'; let value = val; if (value.endsWith(',')) { diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js b/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js index 03dc6bf91014d..d5baf8ded58a9 100644 --- a/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js +++ b/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js @@ -4,13 +4,15 @@ * you may not use this file except in compliance with the Elastic License. */ -export const ADDITION_PREFIX = '$'; -export const REMOVAL_PREFIX = '^'; +export const ADDITION_PREFIX = '$$$'; +export const REMOVAL_PREFIX = '^^^'; +const escapePrefix = prefix => prefix.split('').map(i => `\\${i}`).join(''); const removePrefixRegex = new RegExp( - `(\\${ADDITION_PREFIX}|\\${REMOVAL_PREFIX})`, + `(${escapePrefix(ADDITION_PREFIX)})|(${escapePrefix(REMOVAL_PREFIX)})`, 'g' ); +export const isBoolean = value => JSON.parse(value) === true || JSON.parse(value) === false; const isObject = value => typeof value === 'object' && !Array.isArray(value); const isDifferent = (obj, key, value) => { // If the object does not contain the key, then ignore since it's not a removal or addition @@ -46,7 +48,7 @@ const getAdditions = obj => { export const removePrefixes = str => str.replace(removePrefixRegex, ''); -export const mergeAndPreserveDuplicateKeys = (source, target, result = {}) => { +export const mergeAndPreserveDuplicateKeys = (source, target, result = {}, changes = []) => { for (const [key, value] of Object.entries(source)) { // const debug = key === 'fooobar'; // debug && console.log('mergeAndPreserveDuplicateKeys', key, value, target); @@ -54,10 +56,17 @@ export const mergeAndPreserveDuplicateKeys = (source, target, result = {}) => { // debug && console.log('isDifferent'); result[`${REMOVAL_PREFIX}${key}`] = value; result[`${ADDITION_PREFIX}${key}`] = target[key]; + changes.push({ + key, + original: value, + updated: target[key], + }); } else if (isObject(value)) { // debug && console.log('value is object', target[key]); if (target.hasOwnProperty(key)) { - result[key] = mergeAndPreserveDuplicateKeys(value, target[key]); + const recurseResult = mergeAndPreserveDuplicateKeys(value, target[key]); + result[key] = recurseResult.result; + changes.push(...recurseResult.changes); } else { result[key] = value; } @@ -80,6 +89,10 @@ export const mergeAndPreserveDuplicateKeys = (source, target, result = {}) => { } else { result[`${ADDITION_PREFIX}${key}`] = value; } + changes.push({ + key, + updated: result[`${ADDITION_PREFIX}${key}`], + }); } - return result; + return { result, changes }; }; 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 index f76022a06359a..27d206d1f797b 100644 --- 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 @@ -4,11 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { PureComponent } from 'react'; +import React, { Fragment, PureComponent } from 'react'; import PropTypes from 'prop-types'; -import { EuiCodeEditor } from '@elastic/eui'; - +import { + EuiCodeEditor, + EuiDescriptionList, + EuiDescriptionListTitle, + EuiDescriptionListDescription, + EuiFlexGroup, + EuiFlexItem, + EuiButtonEmpty, +} from '@elastic/eui'; +import ace from 'brace'; import 'brace/mode/json'; import { mergeAndPreserveDuplicateKeys, @@ -24,6 +32,14 @@ export class DiffView extends PureComponent { }).isRequired, }; + scrollToKey = (key, value) => { + const editorDom = this.aceEditor.aceEditor.refEditor; + const editor = ace.edit(editorDom); + const escapedValue = value.replace(/\^/, '\\^'); + const range = editor.find(new RegExp(`"${key}"\\s*:\\s*"*(${escapedValue})"*`), { regex: true }); + editor.gotoLine(range.start.row + 1, range.start.column); + } + render() { const { templateDiff: { originalFullIndexTemplate, newFullIndexTemplate }, @@ -31,12 +47,12 @@ export class DiffView extends PureComponent { // console.log(JSON.stringify(this.props)); - const mergedJson = mergeAndPreserveDuplicateKeys( + const { result: mergedJson, changes } = mergeAndPreserveDuplicateKeys( originalFullIndexTemplate, newFullIndexTemplate ); - // console.log('mergedJson', mergedJson); + // console.log('mergedJson', mergedJson, changes); // Strip the ^ and $ characters const mergedJsonAsString = removePrefixes( @@ -46,18 +62,46 @@ export class DiffView extends PureComponent { addDiffAddonsForAce(mergedJson); return ( - + + + + {changes.map(({ key, original, updated }) => ( + + + this.scrollToKey(key, updated)}> + {key} + + + + {original ? ( + + Changing `{original}` to `{updated}`` + + ) : ( + Adding with `{updated}` + )} + + + ))} + + + + (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/diff.json b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json index f7e2243cbddea..0411f08b735f4 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json @@ -1,2879 +1,284 @@ { "originalFullIndexTemplate": { - "order": 1, - "index_patterns": ["filebeat-7.0.0-alpha1-*"], - "settings": { - "index": { - "lifecycle": { - "name": "my_policy4" - }, - "routing": { - "allocation": { - "include": { - "sattr_name": "lala" - } - } - }, - "mapping": { - "total_fields": { - "limit": "10000" - } - }, - "refresh_interval": "5s", - "number_of_shards": "3", - "number_of_routing_shards": "30", - "number_of_replicas": "0" - } - }, - "mappings": { - "doc": { - "dynamic_templates": [{ - "fields": { - "mapping": { - "type": "keyword" - }, - "match_mapping_type": "string", - "path_match": "fields.*" - } - }, { - "docker.container.labels": { - "mapping": { - "type": "keyword" - }, - "match_mapping_type": "string", - "path_match": "docker.container.labels.*" - } - }, { - "strings_as_keyword": { - "mapping": { - "ignore_above": 1024, - "type": "keyword" - }, - "match_mapping_type": "string" - } - }], - "properties": { - "tags": { - "type": "keyword", - "ignore_above": 1024 - }, - "error": { - "properties": { - "code": { - "type": "long" - }, - "type": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - } - } - }, - "message": { - "type": "text", - "norms": false - }, - "read_timestamp": { - "type": "keyword", - "ignore_above": 1024 - }, - "apache2": { - "properties": { - "access": { - "properties": { - "http_version": { - "type": "keyword", - "ignore_above": 1024 - }, - "response_code": { - "type": "long" - }, - "user_agent": { - "properties": { - "os": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "minor": { - "type": "long" - }, - "major": { - "type": "long" - }, - "patch": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_major": { - "type": "long" - }, - "os_minor": { - "type": "long" - }, - "device": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "geoip": { - "properties": { - "continent_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "country_iso_code": { - "type": "keyword", - "ignore_above": 1024 - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "remote_ip": { - "ignore_above": 1024, - "type": "keyword" - }, - "user_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "method": { - "type": "keyword", - "ignore_above": 1024 - }, - "agent": { - "type": "text", - "norms": false - }, - "url": { - "type": "keyword", - "ignore_above": 1024 - }, - "body_sent": { - "properties": { - "bytes": { - "type": "long" - } - } - }, - "referrer": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "error": { - "properties": { - "client": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - }, - "pid": { - "type": "long" - }, - "tid": { - "type": "long" - }, - "module": { - "ignore_above": 1024, - "type": "keyword" - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "icinga": { - "properties": { - "main": { - "properties": { - "facility": { - "type": "keyword", - "ignore_above": 1024 - }, - "severity": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "norms": false, - "type": "text" - } - } - }, - "startup": { - "properties": { - "facility": { - "type": "keyword", - "ignore_above": 1024 - }, - "severity": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "norms": false, - "type": "text" - } - } - }, - "debug": { - "properties": { - "message": { - "type": "text", - "norms": false - }, - "facility": { - "ignore_above": 1024, - "type": "keyword" - }, - "severity": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "logstash": { - "properties": { - "log": { - "properties": { - "level": { - "type": "keyword", - "ignore_above": 1024 - }, - "module": { - "type": "keyword", - "ignore_above": 1024 - }, - "thread": { - "type": "text", - "norms": false - }, - "log_event": { - "type": "object" - }, - "message": { - "type": "text", - "norms": false - } - } - }, - "slowlog": { - "properties": { - "module": { - "ignore_above": 1024, - "type": "keyword" - }, - "event": { - "type": "text", - "norms": false - }, - "plugin_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "took_in_nanos": { - "type": "long" - }, - "plugin_params": { - "type": "text", - "norms": false - }, - "plugin_params_object": { - "type": "object" - }, - "message": { - "norms": false, - "type": "text" - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - }, - "thread": { - "type": "text", - "norms": false - }, - "plugin_type": { - "type": "keyword", - "ignore_above": 1024 - }, - "took_in_millis": { - "type": "long" - } - } - } - } - }, - "mysql": { - "properties": { - "slowlog": { - "properties": { - "rows_sent": { - "type": "long" - }, - "id": { - "type": "long" - }, - "rows_examined": { - "type": "long" - }, - "timestamp": { - "type": "long" - }, - "query": { - "type": "keyword", - "ignore_above": 1024 - }, - "user": { - "type": "keyword", - "ignore_above": 1024 - }, - "host": { - "type": "keyword", - "ignore_above": 1024 - }, - "ip": { - "ignore_above": 1024, - "type": "keyword" - }, - "query_time": { - "properties": { - "sec": { - "type": "float" - } - } - }, - "lock_time": { - "properties": { - "sec": { - "type": "float" - } - } - } - } - }, - "error": { - "properties": { - "thread_id": { - "type": "long" - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - }, - "timestamp": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "beat": { - "properties": { - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "hostname": { - "type": "keyword", - "ignore_above": 1024 - }, - "timezone": { - "type": "keyword", - "ignore_above": 1024 - }, - "version": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "docker": { - "properties": { - "container": { - "properties": { - "image": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "labels": { - "type": "object" - }, - "id": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "fileset": { - "properties": { - "module": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "@timestamp": { - "type": "date" - }, - "meta": { - "properties": { - "cloud": { - "properties": { - "provider": { - "type": "keyword", - "ignore_above": 1024 - }, - "instance_id": { - "type": "keyword", - "ignore_above": 1024 - }, - "instance_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "machine_type": { - "type": "keyword", - "ignore_above": 1024 - }, - "availability_zone": { - "ignore_above": 1024, - "type": "keyword" - }, - "project_id": { - "type": "keyword", - "ignore_above": 1024 - }, - "region": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "kafka": { - "properties": { - "log": { - "properties": { - "trace": { - "properties": { - "class": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - }, - "full": { - "type": "text", - "norms": false - } - } - }, - "timestamp": { - "type": "keyword", - "ignore_above": 1024 - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - }, - "component": { - "ignore_above": 1024, - "type": "keyword" - }, - "class": { - "type": "text", - "norms": false - } - } - } - } - }, - "redis": { - "properties": { - "slowlog": { - "properties": { - "id": { - "type": "long" - }, - "key": { - "type": "keyword", - "ignore_above": 1024 - }, - "args": { - "type": "keyword", - "ignore_above": 1024 - }, - "cmd": { - "type": "keyword", - "ignore_above": 1024 - }, - "duration": { - "properties": { - "us": { - "type": "long" - } - } - } - } - }, - "log": { - "properties": { - "pid": { - "type": "long" - }, - "role": { - "type": "keyword", - "ignore_above": 1024 - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - } - } - } - } - }, - "input": { - "properties": { - "type": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "iis": { - "properties": { - "access": { - "properties": { - "server_ip": { - "type": "keyword", - "ignore_above": 1024 - }, - "port": { - "type": "long" - }, - "user_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "response_code": { - "type": "long" - }, - "server_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "cookie": { - "type": "keyword", - "ignore_above": 1024 - }, - "method": { - "type": "keyword", - "ignore_above": 1024 - }, - "url": { - "ignore_above": 1024, - "type": "keyword" - }, - "win32_status": { - "type": "long" - }, - "agent": { - "type": "text", - "norms": false - }, - "user_agent": { - "properties": { - "major": { - "type": "long" - }, - "patch": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "os": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_minor": { - "type": "long" - }, - "device": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_major": { - "type": "long" - }, - "os_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "minor": { - "type": "long" - } - } - }, - "query_string": { - "ignore_above": 1024, - "type": "keyword" - }, - "referrer": { - "type": "keyword", - "ignore_above": 1024 - }, - "sub_status": { - "type": "long" - }, - "request_time_ms": { - "type": "long" - }, - "http_version": { - "type": "keyword", - "ignore_above": 1024 - }, - "hostname": { - "type": "keyword", - "ignore_above": 1024 - }, - "body_sent": { - "properties": { - "bytes": { - "type": "long" - } - } - }, - "geoip": { - "properties": { - "continent_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "country_iso_code": { - "type": "keyword", - "ignore_above": 1024 - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "remote_ip": { - "type": "keyword", - "ignore_above": 1024 - }, - "site_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "body_received": { - "properties": { - "bytes": { - "type": "long" - } - } - } - } - }, - "error": { - "properties": { - "remote_port": { - "type": "long" - }, - "server_port": { - "type": "long" - }, - "response_code": { - "type": "long" - }, - "reason_phrase": { - "type": "keyword", - "ignore_above": 1024 - }, - "queue_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "remote_ip": { - "type": "keyword", - "ignore_above": 1024 - }, - "http_version": { - "type": "keyword", - "ignore_above": 1024 - }, - "method": { - "type": "keyword", - "ignore_above": 1024 - }, - "url": { - "type": "keyword", - "ignore_above": 1024 - }, - "geoip": { - "properties": { - "country_iso_code": { - "type": "keyword", - "ignore_above": 1024 - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "continent_name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "server_ip": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "fields": { - "type": "object" - }, - "kubernetes": { - "properties": { - "container": { - "properties": { - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "image": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "pod": { - "properties": { - "name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "namespace": { - "type": "keyword", - "ignore_above": 1024 - }, - "node": { - "properties": { - "name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "labels": { - "type": "object" - }, - "annotations": { - "type": "object" - } - } - }, - "source": { - "type": "keyword", - "ignore_above": 1024 - }, - "auditd": { - "properties": { - "log": { - "properties": { - "geoip": { - "properties": { - "continent_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "country_iso_code": { - "ignore_above": 1024, - "type": "keyword" - }, - "location": { - "type": "geo_point" - } - } - }, - "old_ses": { - "type": "keyword", - "ignore_above": 1024 - }, - "new_ses": { - "type": "keyword", - "ignore_above": 1024 - }, - "res": { - "type": "keyword", - "ignore_above": 1024 - }, - "sequence": { - "type": "long" - }, - "item": { - "type": "keyword", - "ignore_above": 1024 - }, - "items": { - "type": "keyword", - "ignore_above": 1024 - }, - "record_type": { - "type": "keyword", - "ignore_above": 1024 - }, - "old_auid": { - "ignore_above": 1024, - "type": "keyword" - }, - "ppid": { - "type": "keyword", - "ignore_above": 1024 - }, - "a0": { - "type": "keyword", - "ignore_above": 1024 - }, - "new_auid": { - "type": "keyword", - "ignore_above": 1024 - }, - "acct": { - "type": "keyword", - "ignore_above": 1024 - }, - "pid": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "nginx": { - "properties": { - "access": { - "properties": { - "remote_ip": { - "type": "keyword", - "ignore_above": 1024 - }, - "user_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "http_version": { - "type": "keyword", - "ignore_above": 1024 - }, - "user_agent": { - "properties": { - "os_minor": { - "type": "long" - }, - "major": { - "type": "long" - }, - "minor": { - "type": "long" - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_major": { - "type": "long" - }, - "device": { - "type": "keyword", - "ignore_above": 1024 - }, - "patch": { - "type": "keyword", - "ignore_above": 1024 - }, - "os": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "referrer": { - "type": "keyword", - "ignore_above": 1024 - }, - "agent": { - "type": "text", - "norms": false - }, - "geoip": { - "properties": { - "continent_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "country_iso_code": { - "type": "keyword", - "ignore_above": 1024 - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "method": { - "type": "keyword", - "ignore_above": 1024 - }, - "url": { - "type": "keyword", - "ignore_above": 1024 - }, - "response_code": { - "type": "long" - }, - "body_sent": { - "properties": { - "bytes": { - "type": "long" - } - } - } - } - }, - "error": { - "properties": { - "pid": { - "type": "long" - }, - "tid": { - "type": "long" - }, - "connection_id": { - "type": "long" - }, - "message": { - "type": "text", - "norms": false - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "offset": { - "type": "long" - }, - "stream": { - "type": "keyword", - "ignore_above": 1024 - }, - "postgresql": { - "properties": { - "log": { - "properties": { - "timezone": { - "type": "keyword", - "ignore_above": 1024 - }, - "thread_id": { - "type": "long" - }, - "database": { - "type": "keyword", - "ignore_above": 1024 - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - }, - "timestamp": { - "ignore_above": 1024, - "type": "keyword" - }, - "user": { - "type": "keyword", - "ignore_above": 1024 - }, - "duration": { - "type": "float" - }, - "query": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "traefik": { - "properties": { - "access": { - "properties": { - "referrer": { - "type": "keyword", - "ignore_above": 1024 - }, - "geoip": { - "properties": { - "continent_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country_iso_code": { - "type": "keyword", - "ignore_above": 1024 - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "method": { - "ignore_above": 1024, - "type": "keyword" - }, - "body_sent": { - "properties": { - "bytes": { - "type": "long" - } - } - }, - "user_agent": { - "properties": { - "device": { - "type": "keyword", - "ignore_above": 1024 - }, - "minor": { - "type": "long" - }, - "os_minor": { - "type": "long" - }, - "major": { - "type": "long" - }, - "patch": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "os": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_major": { - "type": "long" - }, - "os_name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "frontend_name": { - "type": "text", - "norms": false - }, - "http_version": { - "type": "keyword", - "ignore_above": 1024 - }, - "response_code": { - "type": "long" - }, - "remote_ip": { - "type": "keyword", - "ignore_above": 1024 - }, - "user_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "request_count": { - "type": "long" - }, - "backend_url": { - "type": "text", - "norms": false - }, - "url": { - "ignore_above": 1024, - "type": "keyword" - }, - "agent": { - "type": "text", - "norms": false - } - } - } - } - }, - "prospector": { - "properties": { - "type": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "osquery": { - "properties": { - "result": { - "properties": { - "host_identifier": { - "type": "keyword", - "ignore_above": 1024 - }, - "unix_time": { - "type": "long" - }, - "calendar_time": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "action": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "system": { - "properties": { - "syslog": { - "properties": { - "program": { - "type": "keyword", - "ignore_above": 1024 - }, - "pid": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "type": "keyword", - "ignore_above": 1024 - }, - "timestamp": { - "type": "keyword", - "ignore_above": 1024 - }, - "hostname": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "auth": { - "properties": { - "groupadd": { - "properties": { - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "gid": { - "type": "long" - } - } - }, - "hostname": { - "type": "keyword", - "ignore_above": 1024 - }, - "pid": { - "type": "long" - }, - "user": { - "type": "keyword", - "ignore_above": 1024 - }, - "useradd": { - "properties": { - "home": { - "type": "keyword", - "ignore_above": 1024 - }, - "shell": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "uid": { - "type": "long" - }, - "gid": { - "type": "long" - } - } - }, - "sudo": { - "properties": { - "error": { - "type": "keyword", - "ignore_above": 1024 - }, - "tty": { - "ignore_above": 1024, - "type": "keyword" - }, - "pwd": { - "type": "keyword", - "ignore_above": 1024 - }, - "user": { - "type": "keyword", - "ignore_above": 1024 - }, - "command": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "timestamp": { - "type": "keyword", - "ignore_above": 1024 - }, - "program": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "type": "keyword", - "ignore_above": 1024 - }, - "ssh": { - "properties": { - "geoip": { - "properties": { - "continent_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "country_iso_code": { - "type": "keyword", - "ignore_above": 1024 - }, - "location": { - "type": "geo_point" - } - } - }, - "event": { - "ignore_above": 1024, - "type": "keyword" - }, - "method": { - "type": "keyword", - "ignore_above": 1024 - }, - "ip": { - "type": "ip" - }, - "dropped_ip": { - "type": "ip" - }, - "port": { - "type": "long" - }, - "signature": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - } - } - } - }, - "_meta": { - "version": "7.0.0-alpha1" - }, - "date_detection": false - } - }, - "aliases": {} + "@elastic/eui": "v0.0.44", + "@elastic/filesaver": "1.1.2", + "@elastic/numeral": "2.3.2", + "@elastic/ui-ace": "0.2.3", + "@kbn/babel-preset": "link:packages/kbn-babel-preset", + "@kbn/datemath": "link:packages/kbn-datemath", + "@kbn/pm": "link:packages/kbn-pm", + "@kbn/test-subj-selector": "link:packages/kbn-test-subj-selector", + "@kbn/ui-framework": "link:packages/kbn-ui-framework", + "JSONStream": "1.1.1", + "accept-language-parser": "1.2.0", + "angular": "1.6.9", + "angular-aria": "1.6.6", + "angular-elastic": "2.5.0", + "angular-recursion": "^1.0.5", + "angular-route": "1.4.7", + "angular-sanitize": "1.5.7", + "angular-sortable-view": "0.0.15", + "autoprefixer": "6.5.4", + "babel-core": "6.21.0", + "babel-loader": "7.1.2", + "babel-polyfill": "6.20.0", + "babel-register": "6.18.0", + "bluebird": "2.9.34", + "body-parser": "1.12.0", + "boom": "5.2.0", + "brace": "0.10.0", + "bunyan": "1.7.1", + "cache-loader": "1.0.3", + "chalk": "2.3.0", + "check-hash": "1.0.1", + "color": "1.0.3", + "commander": "2.8.1", + "compare-versions": "3.1.0", + "css-loader": "0.28.7", + "custom-event-polyfill": "^0.3.0", + "d3": "3.5.6", + "d3-cloud": "1.2.1", + "dragula": "3.7.0", + "elasticsearch": "^14.2.1", + "elasticsearch-browser": "^14.2.1", + "encode-uri-query": "1.0.0", + "even-better": "7.0.2", + "expiry-js": "0.1.7", + "extract-text-webpack-plugin": "3.0.1", + "file-loader": "1.1.4", + "font-awesome": "4.4.0", + "glob": "5.0.13", + "glob-all": "3.0.1", + "good-squeeze": "2.1.0", + "h2o2": "5.1.1", + "handlebars": "4.0.5", + "hapi": "14.2.0", + "hjson": "3.1.0", + "http-proxy-agent": "1.0.0", + "https-proxy-agent": "2.1.1", + "inert": "4.0.2", + "jade": "1.11.0", + "jade-loader": "0.8.0", + "joi": "10.4.1", + "jquery": "^3.3.1", + "js-yaml": "3.4.1", + "json-stringify-pretty-compact": "1.0.4", + "json-stringify-safe": "5.0.1", + "jstimezonedetect": "1.0.5", + "leaflet": "1.0.3", + "leaflet-draw": "0.4.10", + "leaflet-responsive-popup": "0.2.0", + "leaflet-vega": "^0.8.6", + "leaflet.heat": "0.2.0", + "less": "2.7.1", + "less-loader": "4.0.5", + "lodash": "3.10.1", + "lru-cache": "4.1.1", + "markdown-it": "8.3.2", + "minimatch": "2.0.10", + "mkdirp": "0.5.1", + "moment": "^2.20.1", + "moment-timezone": "^0.5.14", + "mustache": "2.3.0", + "ngreact": "0.5.1", + "no-ui-slider": "1.2.0", + "node-fetch": "1.3.2", + "pegjs": "0.9.0", + "postcss-loader": "2.0.6", + "prop-types": "15.5.8", + "proxy-from-env": "1.0.0", + "querystring-browser": "1.0.4", + "raw-loader": "0.5.1", + "react": "^16.2.0", + "react-addons-shallow-compare": "15.6.2", + "react-anything-sortable": "^1.7.4", + "react-color": "^2.13.8", + "react-dom": "^16.2.0", + "react-grid-layout": "^0.16.2", + "react-input-range": "^1.3.0", + "react-markdown": "^3.1.4", + "react-redux": "^5.0.6", + "react-router-dom": "4.2.2", + "react-select": "^1.2.0", + "react-sizeme": "^2.3.6", + "react-toggle": "4.0.2", + "reactcss": "1.2.3", + "redux": "3.7.2", + "redux-actions": "2.2.1", + "redux-thunk": "2.2.0", + "regression": "2.0.0", + "request": "^2.85.0", + "reselect": "^3.0.1", + "resize-observer-polyfill": "1.2.1", + "rimraf": "2.4.3", + "rison-node": "1.0.0", + "rxjs": "5.4.3", + "script-loader": "0.7.2", + "semver": "5.1.0", + "style-loader": "0.19.0", + "tar": "2.2.0", + "tinygradient": "0.3.0", + "tinymath": "0.2.1", + "topojson-client": "3.0.0", + "trunc-html": "1.0.2", + "trunc-text": "1.0.2", + "uglifyjs-webpack-plugin": "0.4.6", + "ui-select": "0.19.6", + "url-loader": "0.5.9", + "uuid": "3.0.1", + "validate-npm-package-name": "2.2.2", + "vega-lib": "^3.3.1", + "vega-lite": "^2.4.0", + "vega-tooltip": "^0.9.14", + "vega-schema-url-parser": "1.0.0", + "vision": "4.1.0", + "webpack": "3.6.0", + "webpack-merge": "4.1.0", + "whatwg-fetch": "^2.0.3", + "wreck": "12.4.0", + "x-pack": "link:x-pack", + "yauzl": "2.7.0" }, "newFullIndexTemplate": { - "order": 1, - "index_patterns": ["filebeat-7.0.0-alpha1-*"], - "settings": { - "index": { - "lifecycle": { - "name": "my_policy41" - }, - "routing": { - "allocation": { - "include": { - "sattr_name": "warm_node:true" - } - } - }, - "mapping": { - "total_fields": { - "limit": "10000" - } - }, - "refresh_interval": "5s", - "number_of_shards": "3", - "number_of_routing_shards": "30", - "number_of_replicas": "1" - } - }, - "mappings": { - "doc": { - "dynamic_templates": [{ - "fields": { - "mapping": { - "type": "keyword" - }, - "match_mapping_type": "string", - "path_match": "fields.*" - } - }, { - "docker.container.labels": { - "mapping": { - "type": "keyword" - }, - "match_mapping_type": "string", - "path_match": "docker.container.labels.*" - } - }, { - "strings_as_keyword": { - "mapping": { - "ignore_above": 1024, - "type": "keyword" - }, - "match_mapping_type": "string" - } - }], - "properties": { - "tags": { - "type": "keyword", - "ignore_above": 1024 - }, - "error": { - "properties": { - "code": { - "type": "long" - }, - "type": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - } - } - }, - "message": { - "type": "text", - "norms": false - }, - "read_timestamp": { - "type": "keyword", - "ignore_above": 1024 - }, - "apache2": { - "properties": { - "access": { - "properties": { - "http_version": { - "type": "keyword", - "ignore_above": 1024 - }, - "response_code": { - "type": "long" - }, - "user_agent": { - "properties": { - "os": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "minor": { - "type": "long" - }, - "major": { - "type": "long" - }, - "patch": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_major": { - "type": "long" - }, - "os_minor": { - "type": "long" - }, - "device": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "geoip": { - "properties": { - "continent_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "country_iso_code": { - "type": "keyword", - "ignore_above": 1024 - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "remote_ip": { - "ignore_above": 1024, - "type": "keyword" - }, - "user_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "method": { - "type": "keyword", - "ignore_above": 1024 - }, - "agent": { - "type": "text", - "norms": false - }, - "url": { - "type": "keyword", - "ignore_above": 1024 - }, - "body_sent": { - "properties": { - "bytes": { - "type": "long" - } - } - }, - "referrer": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "error": { - "properties": { - "client": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - }, - "pid": { - "type": "long" - }, - "tid": { - "type": "long" - }, - "module": { - "ignore_above": 1024, - "type": "keyword" - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "icinga": { - "properties": { - "main": { - "properties": { - "facility": { - "type": "keyword", - "ignore_above": 1024 - }, - "severity": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "norms": false, - "type": "text" - } - } - }, - "startup": { - "properties": { - "facility": { - "type": "keyword", - "ignore_above": 1024 - }, - "severity": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "norms": false, - "type": "text" - } - } - }, - "debug": { - "properties": { - "message": { - "type": "text", - "norms": false - }, - "facility": { - "ignore_above": 1024, - "type": "keyword" - }, - "severity": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "logstash": { - "properties": { - "log": { - "properties": { - "level": { - "type": "keyword", - "ignore_above": 1024 - }, - "module": { - "type": "keyword", - "ignore_above": 1024 - }, - "thread": { - "type": "text", - "norms": false - }, - "log_event": { - "type": "object" - }, - "message": { - "type": "text", - "norms": false - } - } - }, - "slowlog": { - "properties": { - "module": { - "ignore_above": 1024, - "type": "keyword" - }, - "event": { - "type": "text", - "norms": false - }, - "plugin_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "took_in_nanos": { - "type": "long" - }, - "plugin_params": { - "type": "text", - "norms": false - }, - "plugin_params_object": { - "type": "object" - }, - "message": { - "norms": false, - "type": "text" - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - }, - "thread": { - "type": "text", - "norms": false - }, - "plugin_type": { - "type": "keyword", - "ignore_above": 1024 - }, - "took_in_millis": { - "type": "long" - } - } - } - } - }, - "mysql": { - "properties": { - "slowlog": { - "properties": { - "rows_sent": { - "type": "long" - }, - "id": { - "type": "long" - }, - "rows_examined": { - "type": "long" - }, - "timestamp": { - "type": "long" - }, - "query": { - "type": "keyword", - "ignore_above": 1024 - }, - "user": { - "type": "keyword", - "ignore_above": 1024 - }, - "host": { - "type": "keyword", - "ignore_above": 1024 - }, - "ip": { - "ignore_above": 1024, - "type": "keyword" - }, - "query_time": { - "properties": { - "sec": { - "type": "float" - } - } - }, - "lock_time": { - "properties": { - "sec": { - "type": "float" - } - } - } - } - }, - "error": { - "properties": { - "thread_id": { - "type": "long" - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - }, - "timestamp": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "beat": { - "properties": { - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "hostname": { - "type": "keyword", - "ignore_above": 1024 - }, - "timezone": { - "type": "keyword", - "ignore_above": 1024 - }, - "version": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "docker": { - "properties": { - "container": { - "properties": { - "image": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "labels": { - "type": "object" - }, - "id": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "fileset": { - "properties": { - "module": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "@timestamp": { - "type": "date" - }, - "meta": { - "properties": { - "cloud": { - "properties": { - "provider": { - "type": "keyword", - "ignore_above": 1024 - }, - "instance_id": { - "type": "keyword", - "ignore_above": 1024 - }, - "instance_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "machine_type": { - "type": "keyword", - "ignore_above": 1024 - }, - "availability_zone": { - "ignore_above": 1024, - "type": "keyword" - }, - "project_id": { - "type": "keyword", - "ignore_above": 1024 - }, - "region": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "kafka": { - "properties": { - "log": { - "properties": { - "trace": { - "properties": { - "class": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - }, - "full": { - "type": "text", - "norms": false - } - } - }, - "timestamp": { - "type": "keyword", - "ignore_above": 1024 - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - }, - "component": { - "ignore_above": 1024, - "type": "keyword" - }, - "class": { - "type": "text", - "norms": false - } - } - } - } - }, - "redis": { - "properties": { - "slowlog": { - "properties": { - "id": { - "type": "long" - }, - "key": { - "type": "keyword", - "ignore_above": 1024 - }, - "args": { - "type": "keyword", - "ignore_above": 1024 - }, - "cmd": { - "type": "keyword", - "ignore_above": 1024 - }, - "duration": { - "properties": { - "us": { - "type": "long" - } - } - } - } - }, - "log": { - "properties": { - "pid": { - "type": "long" - }, - "role": { - "type": "keyword", - "ignore_above": 1024 - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - } - } - } - } - }, - "input": { - "properties": { - "type": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "iis": { - "properties": { - "access": { - "properties": { - "server_ip": { - "type": "keyword", - "ignore_above": 1024 - }, - "port": { - "type": "long" - }, - "user_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "response_code": { - "type": "long" - }, - "server_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "cookie": { - "type": "keyword", - "ignore_above": 1024 - }, - "method": { - "type": "keyword", - "ignore_above": 1024 - }, - "url": { - "ignore_above": 1024, - "type": "keyword" - }, - "win32_status": { - "type": "long" - }, - "agent": { - "type": "text", - "norms": false - }, - "user_agent": { - "properties": { - "major": { - "type": "long" - }, - "patch": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "os": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_minor": { - "type": "long" - }, - "device": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_major": { - "type": "long" - }, - "os_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "minor": { - "type": "long" - } - } - }, - "query_string": { - "ignore_above": 1024, - "type": "keyword" - }, - "referrer": { - "type": "keyword", - "ignore_above": 1024 - }, - "sub_status": { - "type": "long" - }, - "request_time_ms": { - "type": "long" - }, - "http_version": { - "type": "keyword", - "ignore_above": 1024 - }, - "hostname": { - "type": "keyword", - "ignore_above": 1024 - }, - "body_sent": { - "properties": { - "bytes": { - "type": "long" - } - } - }, - "geoip": { - "properties": { - "continent_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "country_iso_code": { - "type": "keyword", - "ignore_above": 1024 - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "remote_ip": { - "type": "keyword", - "ignore_above": 1024 - }, - "site_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "body_received": { - "properties": { - "bytes": { - "type": "long" - } - } - } - } - }, - "error": { - "properties": { - "remote_port": { - "type": "long" - }, - "server_port": { - "type": "long" - }, - "response_code": { - "type": "long" - }, - "reason_phrase": { - "type": "keyword", - "ignore_above": 1024 - }, - "queue_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "remote_ip": { - "type": "keyword", - "ignore_above": 1024 - }, - "http_version": { - "type": "keyword", - "ignore_above": 1024 - }, - "method": { - "type": "keyword", - "ignore_above": 1024 - }, - "url": { - "type": "keyword", - "ignore_above": 1024 - }, - "geoip": { - "properties": { - "country_iso_code": { - "type": "keyword", - "ignore_above": 1024 - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "continent_name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "server_ip": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "fields": { - "type": "object" - }, - "kubernetes": { - "properties": { - "container": { - "properties": { - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "image": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "pod": { - "properties": { - "name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "namespace": { - "type": "keyword", - "ignore_above": 1024 - }, - "node": { - "properties": { - "name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "labels": { - "type": "object" - }, - "annotations": { - "type": "object" - } - } - }, - "source": { - "type": "keyword", - "ignore_above": 1024 - }, - "auditd": { - "properties": { - "log": { - "properties": { - "geoip": { - "properties": { - "continent_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "country_iso_code": { - "ignore_above": 1024, - "type": "keyword" - }, - "location": { - "type": "geo_point" - } - } - }, - "old_ses": { - "type": "keyword", - "ignore_above": 1024 - }, - "new_ses": { - "type": "keyword", - "ignore_above": 1024 - }, - "res": { - "type": "keyword", - "ignore_above": 1024 - }, - "sequence": { - "type": "long" - }, - "item": { - "type": "keyword", - "ignore_above": 1024 - }, - "items": { - "type": "keyword", - "ignore_above": 1024 - }, - "record_type": { - "type": "keyword", - "ignore_above": 1024 - }, - "old_auid": { - "ignore_above": 1024, - "type": "keyword" - }, - "ppid": { - "type": "keyword", - "ignore_above": 1024 - }, - "a0": { - "type": "keyword", - "ignore_above": 1024 - }, - "new_auid": { - "type": "keyword", - "ignore_above": 1024 - }, - "acct": { - "type": "keyword", - "ignore_above": 1024 - }, - "pid": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "nginx": { - "properties": { - "access": { - "properties": { - "remote_ip": { - "type": "keyword", - "ignore_above": 1024 - }, - "user_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "http_version": { - "type": "keyword", - "ignore_above": 1024 - }, - "user_agent": { - "properties": { - "os_minor": { - "type": "long" - }, - "major": { - "type": "long" - }, - "minor": { - "type": "long" - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_major": { - "type": "long" - }, - "device": { - "type": "keyword", - "ignore_above": 1024 - }, - "patch": { - "type": "keyword", - "ignore_above": 1024 - }, - "os": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_name": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "referrer": { - "type": "keyword", - "ignore_above": 1024 - }, - "agent": { - "type": "text", - "norms": false - }, - "geoip": { - "properties": { - "continent_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "country_iso_code": { - "type": "keyword", - "ignore_above": 1024 - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "method": { - "type": "keyword", - "ignore_above": 1024 - }, - "url": { - "type": "keyword", - "ignore_above": 1024 - }, - "response_code": { - "type": "long" - }, - "body_sent": { - "properties": { - "bytes": { - "type": "long" - } - } - } - } - }, - "error": { - "properties": { - "pid": { - "type": "long" - }, - "tid": { - "type": "long" - }, - "connection_id": { - "type": "long" - }, - "message": { - "type": "text", - "norms": false - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "offset": { - "type": "long" - }, - "stream": { - "type": "keyword", - "ignore_above": 1024 - }, - "postgresql": { - "properties": { - "log": { - "properties": { - "timezone": { - "type": "keyword", - "ignore_above": 1024 - }, - "thread_id": { - "type": "long" - }, - "database": { - "type": "keyword", - "ignore_above": 1024 - }, - "level": { - "type": "keyword", - "ignore_above": 1024 - }, - "message": { - "type": "text", - "norms": false - }, - "timestamp": { - "ignore_above": 1024, - "type": "keyword" - }, - "user": { - "type": "keyword", - "ignore_above": 1024 - }, - "duration": { - "type": "float" - }, - "query": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "traefik": { - "properties": { - "access": { - "properties": { - "referrer": { - "type": "keyword", - "ignore_above": 1024 - }, - "geoip": { - "properties": { - "continent_name": { - "ignore_above": 1024, - "type": "keyword" - }, - "country_iso_code": { - "type": "keyword", - "ignore_above": 1024 - }, - "location": { - "type": "geo_point" - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "method": { - "ignore_above": 1024, - "type": "keyword" - }, - "body_sent": { - "properties": { - "bytes": { - "type": "long" - } - } - }, - "user_agent": { - "properties": { - "device": { - "type": "keyword", - "ignore_above": 1024 - }, - "minor": { - "type": "long" - }, - "os_minor": { - "type": "long" - }, - "major": { - "type": "long" - }, - "patch": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "os": { - "type": "keyword", - "ignore_above": 1024 - }, - "os_major": { - "type": "long" - }, - "os_name": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "frontend_name": { - "type": "text", - "norms": false - }, - "http_version": { - "type": "keyword", - "ignore_above": 1024 - }, - "response_code": { - "type": "long" - }, - "remote_ip": { - "type": "keyword", - "ignore_above": 1024 - }, - "user_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "request_count": { - "type": "long" - }, - "backend_url": { - "type": "text", - "norms": false - }, - "url": { - "ignore_above": 1024, - "type": "keyword" - }, - "agent": { - "type": "text", - "norms": false - } - } - } - } - }, - "prospector": { - "properties": { - "type": { - "ignore_above": 1024, - "type": "keyword" - } - } - }, - "osquery": { - "properties": { - "result": { - "properties": { - "host_identifier": { - "type": "keyword", - "ignore_above": 1024 - }, - "unix_time": { - "type": "long" - }, - "calendar_time": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "action": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - }, - "system": { - "properties": { - "syslog": { - "properties": { - "program": { - "type": "keyword", - "ignore_above": 1024 - }, - "pid": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "type": "keyword", - "ignore_above": 1024 - }, - "timestamp": { - "type": "keyword", - "ignore_above": 1024 - }, - "hostname": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "auth": { - "properties": { - "groupadd": { - "properties": { - "name": { - "ignore_above": 1024, - "type": "keyword" - }, - "gid": { - "type": "long" - } - } - }, - "hostname": { - "type": "keyword", - "ignore_above": 1024 - }, - "pid": { - "type": "long" - }, - "user": { - "type": "keyword", - "ignore_above": 1024 - }, - "useradd": { - "properties": { - "home": { - "type": "keyword", - "ignore_above": 1024 - }, - "shell": { - "type": "keyword", - "ignore_above": 1024 - }, - "name": { - "type": "keyword", - "ignore_above": 1024 - }, - "uid": { - "type": "long" - }, - "gid": { - "type": "long" - } - } - }, - "sudo": { - "properties": { - "error": { - "type": "keyword", - "ignore_above": 1024 - }, - "tty": { - "ignore_above": 1024, - "type": "keyword" - }, - "pwd": { - "type": "keyword", - "ignore_above": 1024 - }, - "user": { - "type": "keyword", - "ignore_above": 1024 - }, - "command": { - "type": "keyword", - "ignore_above": 1024 - } - } - }, - "timestamp": { - "type": "keyword", - "ignore_above": 1024 - }, - "program": { - "ignore_above": 1024, - "type": "keyword" - }, - "message": { - "type": "keyword", - "ignore_above": 1024 - }, - "ssh": { - "properties": { - "geoip": { - "properties": { - "continent_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "city_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "region_name": { - "type": "keyword", - "ignore_above": 1024 - }, - "country_iso_code": { - "type": "keyword", - "ignore_above": 1024 - }, - "location": { - "type": "geo_point" - } - } - }, - "event": { - "ignore_above": 1024, - "type": "keyword" - }, - "method": { - "type": "keyword", - "ignore_above": 1024 - }, - "ip": { - "type": "ip" - }, - "dropped_ip": { - "type": "ip" - }, - "port": { - "type": "long" - }, - "signature": { - "type": "keyword", - "ignore_above": 1024 - } - } - } - } - } - } - } - }, - "_meta": { - "version": "7.0.0-alpha1" - }, - "date_detection": false - } - }, - "aliases": {} + "@elastic/eui": "v0.0.44", + "@elastic/filesaver": "1.1.2", + "@elastic/numeral": "2.3.2", + "@elastic/ui-ace": "0.2.3", + "@kbn/babel-preset": "link:packages/kbn-babel-preset", + "@kbn/datemath": "link:packages/kbn-datemath", + "@kbn/pm": "link:packages/kbn-pm", + "@kbn/test-subj-selector": "link:packages/kbn-test-subj-selector", + "@kbn/ui-framework": "link:packages/kbn-ui-framework", + "JSONStream": "1.1.1", + "accept-language-parser": "1.2.0", + "angular": "1.6.9", + "angular-aria": "1.6.6", + "angular-elastic": "2.5.0", + "angular-recursion": "^1.0.5", + "angular-route": "1.4.7", + "angular-sanitize": "1.5.7", + "angular-sortable-view": "0.0.15", + "autoprefixer": "6.5.4", + "babel-core": "6.21.0", + "babel-loader": "7.1.2", + "babel-polyfill": "6.20.0", + "babel-register": "6.18.0", + "bluebird": "2.9.34", + "body-parser": "1.12.0", + "boom": "5.2.0", + "brace": "0.10.0", + "bunyan": "1.7.1", + "cache-loader": "1.0.3", + "chalk": "2.3.0", + "check-hash": "1.0.1", + "color": "1.0.3", + "commander": "2.8.1", + "compare-versions": "3.1.0", + "css-loader": "0.28.7", + "custom-event-polyfill": "^0.3.0", + "d3": "3.5.6", + "d3-cloud": "1.2.1", + "dragula": "3.7.0", + "elasticsearch": "^14.2.1", + "elasticsearch-browser": "^14.2.1", + "encode-uri-query": "1.0.0", + "even-better": "7.0.2", + "expiry-js": "0.1.7", + "extract-text-webpack-plugin": "3.0.1", + "file-loader": "1.1.4", + "font-awesome": "4.4.0", + "glob": "5.0.13", + "glob-all": "3.0.1", + "good-squeeze": "2.1.0", + "h2o2": "5.1.1", + "handlebars": "4.0.5", + "hapi": "14.2.0", + "hjson": "3.1.0", + "http-proxy-agent": "1.0.0", + "https-proxy-agent": "2.1.1", + "inert": "4.0.2", + "jade": "1.11.0", + "jade-loader": "0.8.0", + "joi": "10.4.1", + "jquery": "^3.3.1", + "js-yaml": "3.4.1", + "json-stringify-pretty-compact": "1.0.4", + "json-stringify-safe": "5.0.1", + "jstimezonedetect": "1.0.5", + "leaflet": "1.0.3", + "leaflet-draw": "0.4.10", + "leaflet-responsive-popup": "0.2.0", + "leaflet-vega": "^0.8.6", + "leaflet.heat": "0.2.0", + "less": "2.7.1", + "less-loader": "4.0.5", + "lodash": "3.10.1", + "lru-cache": "4.1.1", + "markdown-it": "8.3.2", + "minimatch": "2.0.10", + "mkdirp": "0.5.1", + "moment": "^2.20.1", + "moment-timezone": "^0.5.14", + "mustache": "2.3.0", + "ngreact": "0.5.1", + "no-ui-slider": "1.2.0", + "node-fetch": "1.3.2", + "pegjs": "0.9.0", + "postcss-loader": "2.0.6", + "prop-types": "15.5.8", + "proxy-from-env": "1.0.0", + "querystring-browser": "1.0.4", + "raw-loader": "0.5.1", + "react": "^16.3.0", + "react-addons-shallow-compare": "15.6.2", + "react-anything-sortable": "^1.7.4", + "react-color": "^2.13.8", + "react-dom": "^16.3.0", + "react-grid-layout": "^0.16.2", + "react-input-range": "^1.3.0", + "react-markdown": "^3.1.4", + "react-redux": "^5.0.6", + "react-router-dom": "4.2.2", + "react-select": "^1.2.0", + "react-sizeme": "^2.3.6", + "react-toggle": "4.0.2", + "reactcss": "1.2.3", + "redux": "3.7.2", + "redux-actions": "2.2.1", + "redux-thunk": "2.2.0", + "regression": "2.0.0", + "request": "^2.85.0", + "reselect": "^3.0.1", + "resize-observer-polyfill": "1.2.1", + "rimraf": "2.4.3", + "rison-node": "1.0.0", + "rxjs": "5.4.3", + "script-loader": "0.7.2", + "semver": "5.1.0", + "style-loader": "0.19.0", + "tar": "2.2.0", + "tinygradient": "0.3.0", + "tinymath": "0.2.1", + "topojson-client": "3.0.0", + "trunc-html": "1.0.2", + "trunc-text": "1.0.2", + "uglifyjs-webpack-plugin": "0.4.6", + "ui-select": "0.19.6", + "url-loader": "0.5.9", + "uuid": "3.0.2", + "validate-npm-package-name": "2.2.2", + "vega-lib": "^3.3.1", + "vega-lite": "^2.4.0", + "vega-tooltip": "^0.9.14", + "vega-schema-url-parser": "1.0.0", + "vision": "4.1.0", + "webpack": "3.6.0", + "webpack-merge": "4.1.0", + "whatwg-fetch": "^2.0.3", + "wreck": "12.4.0", + "x-pack": "link:x-pack", + "yauzl": "2.7.0", + "zzz": "1.0.0" }, "hasChanged": true } From b2251b63d5f9afcca9073f33eb1bd9f1647322df Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 7 May 2018 13:51:02 -0400 Subject: [PATCH 07/62] Some feedback on copy --- .../components/configuration/configuration.js | 32 ++++++++++++----- .../template_selection/template_selection.js | 12 ++----- .../index_template/index_template.js | 35 ++++++++++++++----- 3 files changed, 52 insertions(+), 27 deletions(-) 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 index 7acd83c378a41..0709a5d9c41d6 100644 --- 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 @@ -4,7 +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 { @@ -18,6 +18,8 @@ import { EuiCallOut, EuiFormRow, EuiButtonEmpty, + EuiIconTip, + EuiLink, } from '@elastic/eui'; import { STRUCTURE_NODE_ATTRS, @@ -82,12 +84,11 @@ export class Configuration extends Component { const primaryNodeErrors = isPrimaryShardCountHigherThanSelectedNodeAttrsCount ? ( - The selected primary shard count is higher than the number of nodes - matching the selected attributes. + The shard count should be lower than the number of nodes that match the selected attributes. ) : null; @@ -101,7 +102,16 @@ export class Configuration extends Component { + Where do you want your hot indices to live +   + + + } errorKey={STRUCTURE_NODE_ATTRS} isShowingErrors={isShowingErrors} errors={errors} @@ -125,15 +135,21 @@ export class Configuration extends Component { this.setState({ isShowingNodeDetailsFlyout: true }) } > - See more details about these nodes + View node details ) : null} - -

Optimize these values for throughput. (Add more)

+ +

+ The best way to determine how many shards you need is to benchmark + using realistic data and queries on your hardware.{' '} + + Learn more. + +

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 index 5828749b4f70c..808c0e1dc3caa 100644 --- 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 @@ -7,7 +7,7 @@ import React, { Fragment, PureComponent } from 'react'; import PropTypes from 'prop-types'; -import { EuiSelect, EuiLink } from '@elastic/eui'; +import { EuiSelect } from '@elastic/eui'; import { ErrableFormRow } from '../../../../form_errors'; import { STRUCTURE_TEMPLATE_NAME } from '../../../../../../store/constants'; @@ -57,18 +57,10 @@ export class TemplateSelection extends PureComponent { {/* {noMatchingIndicesWarning} */} - Learn how to{' '} - - add a new index template - . - - } > { this.setState({ isShowingErrors: true }); if (await this.validate()) { this.props.done(); } - } + }; render() { const { errors } = this.props; @@ -58,6 +60,21 @@ export class IndexTemplate extends Component {

Select a template

+ + + + +
+ A template defines the settings, mappings, and aliases to apply + when you create an index. +
+
+ + + Learn more + +
+
Date: Fri, 11 May 2018 14:59:02 -0400 Subject: [PATCH 08/62] Updating copy, moving components around and fixing bugs with the diff view --- .../public/api/index.js | 7 +- .../public/lib/diff_ace_addons.js | 48 +-- .../public/lib/diff_tools.js | 68 +++- .../components/configuration/configuration.js | 76 ++--- .../template_selection.container.js | 16 +- .../template_selection/template_selection.js | 75 +++-- .../index_template/index_template.js | 5 +- .../node_attrs_details.container.js | 3 +- .../node_attrs_details/node_attrs_details.js | 34 +- .../components/cold_phase/cold_phase.js | 59 ++-- .../components/delete_phase/delete_phase.js | 3 +- .../components/hot_phase/hot_phase.js | 42 +-- .../components/warm_phase/warm_phase.js | 215 ++++++++----- .../policy_configuration.container.js | 7 +- .../policy_configuration.js | 95 +++--- .../policy_selection/policy_selection.js | 25 +- .../wizard/components/review/diff_view.js | 18 +- .../components/review/review.container.js | 12 +- .../wizard/components/review/review.js | 135 ++++++-- .../public/sections/wizard/diff.json | 303 ++---------------- .../public/sections/wizard/wizard.js | 47 +-- .../public/store/constants.js | 14 +- .../public/store/reducers/policies.js | 7 +- .../public/store/selectors/index_template.js | 20 +- .../public/store/selectors/lifecycle.js | 51 ++- .../public/store/selectors/policies.js | 1 + .../indices/register_get_affected_route.js | 28 +- .../api/templates/register_fetch_route.js | 1 + 28 files changed, 720 insertions(+), 695 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 1ce9bdb957c40..c82f07b7d6556 100644 --- a/x-pack/plugins/index_lifecycle_management/public/api/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/api/index.js @@ -11,6 +11,8 @@ export const setHttpClient = (client) => { }; const apiPrefix = chrome.addBasePath('/api/index_lifecycle_management'); +console.log('apiPrefix', apiPrefix); + export async function loadNodes() { const response = await httpClient.get(`${apiPrefix}/nodes/list`); return response.data; @@ -47,6 +49,9 @@ export async function bootstrap(indexName, aliasName) { } export async function getAffectedIndices(indexTemplateName, policyName) { - const response = await httpClient.get(`${apiPrefix}/indices/affected/${indexTemplateName}/${policyName}`); + const path = policyName + ? `${apiPrefix}/indices/affected/${indexTemplateName}/${encodeURIComponent(policyName)}` + : `${apiPrefix}/indices/affected/${indexTemplateName}`; + const response = await httpClient.get(path); return response.data; } diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js b/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js index f1f3b0a018d94..31e64a3c5b1d7 100644 --- a/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js +++ b/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js @@ -6,24 +6,30 @@ import ace from 'brace'; import { ADDITION_PREFIX, REMOVAL_PREFIX } from './diff_tools'; -function findInObject(key, obj) { +function findInObject(key, obj, debug) { + // debug && console.log('findInObject()', key, obj); const objKeys = Object.keys(obj); for (const objKey of objKeys) { if (objKey === key) { + // debug && console.log('findInObject() FOUND', key); return obj[objKey]; } if (typeof obj[objKey] === 'object' && !Array.isArray(obj[objKey])) { - const item = findInObject(key, obj[objKey]); + const item = findInObject(key, obj[objKey], debug); if (item !== false) { + // debug && console.log('findInObject() FOUND 2', key); return item; } } } + // debug && console.log('findInObject() NOT FOUND', key); return false; } function getDiffClasses(key, val, jsonObject) { - // const debug = key === 'react'; + const debug = false;//key === 'name' && val === '"t"'; + + debug && console.log('getDiffClasses()', key, val); let value = val; if (value.endsWith(',')) { @@ -33,15 +39,15 @@ function getDiffClasses(key, val, jsonObject) { value = value.slice(1, -1); } - const additionValue = findInObject(`${ADDITION_PREFIX}${key}`, jsonObject); - const removalValue = findInObject(`${REMOVAL_PREFIX}${key}`, jsonObject); + const additionValue = findInObject(`${ADDITION_PREFIX}${key}`, jsonObject, debug); + const removalValue = findInObject(`${REMOVAL_PREFIX}${key}`, jsonObject, debug); const isAddition = Array.isArray(additionValue) ? !!additionValue.find(v => v === value) - : additionValue === value; + : (additionValue === value || (additionValue && value === '{')); const isRemoval = Array.isArray(removalValue) ? !!removalValue.find(v => v === value) - : removalValue === value; + : (removalValue === value || (removalValue && value === '{')); let diffClasses = ''; if (isAddition) { @@ -52,20 +58,24 @@ function getDiffClasses(key, val, jsonObject) { diffClasses = 'variable'; } - // debug && console.log(`getDiffClasses() - // key='${key}' - // value='${value}' - // additionValue='${additionValue}' - // removalValue='${removalValue}' - // isAddition=${isAddition} - // isRemoval=${isRemoval} - // diffClasses='${diffClasses}' - // `); + debug && console.log(`getDiffClasses() + key='${key}' + value='${value}' + additionValue='${additionValue}' + removalValue='${removalValue}' + isAddition=${isAddition} + isRemoval=${isRemoval} + diffClasses='${diffClasses}' + `); return diffClasses; } -export const addDiffAddonsForAce = jsonObject => { +let currentJsonObject; +const getCurrentJsonObject = () => currentJsonObject; +export const setCurrentJsonObject = jsonObject => currentJsonObject = jsonObject; + +export const addDiffAddonsForAce = () => { const JsonHighlightRules = ace.acequire('ace/mode/json_highlight_rules') .JsonHighlightRules; class DiffJsonHighlightRules extends JsonHighlightRules { @@ -78,7 +88,7 @@ export const addDiffAddonsForAce = jsonObject => { start: [ { token: (key, val) => { - return getDiffClasses(key, val, jsonObject); + return getDiffClasses(key, val, getCurrentJsonObject()); }, regex: '(?:"([\\w-+]+)"\\s*:\\s*([^\\n\\[]+)$)', }, @@ -95,7 +105,7 @@ export const addDiffAddonsForAce = jsonObject => { array: [ { token: val => { - return getDiffClasses(currentArrayKey, val, jsonObject); + return getDiffClasses(currentArrayKey, val, getCurrentJsonObject()); }, next: 'start', regex: '\\s*"([^"]+)"\\s*', diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js b/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js index d5baf8ded58a9..30e4dacbb3cfb 100644 --- a/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js +++ b/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js @@ -6,13 +6,18 @@ export const ADDITION_PREFIX = '$$$'; export const REMOVAL_PREFIX = '^^^'; -const escapePrefix = prefix => prefix.split('').map(i => `\\${i}`).join(''); +const escapePrefix = prefix => + prefix + .split('') + .map(i => `\\${i}`) + .join(''); const removePrefixRegex = new RegExp( `(${escapePrefix(ADDITION_PREFIX)})|(${escapePrefix(REMOVAL_PREFIX)})`, 'g' ); -export const isBoolean = value => JSON.parse(value) === true || JSON.parse(value) === false; +export const isBoolean = value => + JSON.parse(value) === true || JSON.parse(value) === false; const isObject = value => typeof value === 'object' && !Array.isArray(value); const isDifferent = (obj, key, value) => { // If the object does not contain the key, then ignore since it's not a removal or addition @@ -46,9 +51,49 @@ const getAdditions = obj => { return result; }; -export const removePrefixes = str => str.replace(removePrefixRegex, ''); +export const removePrefixes = obj => { + if (typeof obj === 'string') { + return obj.replace(removePrefixRegex, ''); + } + + if (!obj || typeof obj !== 'object') { + return obj; + } + + return Object.keys(obj).reduce( + (newObj, key) => ({ + ...newObj, + [key.replace(removePrefixRegex, '')]: obj[key] && typeof obj[key] === 'object' ? + removePrefixes(obj[key]) : + obj[key], + }), {} + ); +}; -export const mergeAndPreserveDuplicateKeys = (source, target, result = {}, changes = []) => { +const normalizeChange = (key, value) => { + if (typeof value === 'string') { + return { + key: removePrefixes(key), + value: removePrefixes(value) + }; + } + return Object.entries(value).reduce((accum, [key, value]) => { + if (typeof value === 'string') { + return { + key: removePrefixes(key), + value: removePrefixes(value) + }; + } + return normalizeChange(key, value); + }, {}); +}; + +export const mergeAndPreserveDuplicateKeys = ( + source, + target, + result = {}, + changes = [] +) => { for (const [key, value] of Object.entries(source)) { // const debug = key === 'fooobar'; // debug && console.log('mergeAndPreserveDuplicateKeys', key, value, target); @@ -58,8 +103,8 @@ export const mergeAndPreserveDuplicateKeys = (source, target, result = {}, chang result[`${ADDITION_PREFIX}${key}`] = target[key]; changes.push({ key, - original: value, - updated: target[key], + original: removePrefixes(value), + updated: removePrefixes(target[key]), }); } else if (isObject(value)) { // debug && console.log('value is object', target[key]); @@ -89,10 +134,15 @@ export const mergeAndPreserveDuplicateKeys = (source, target, result = {}, chang } else { result[`${ADDITION_PREFIX}${key}`] = value; } + + const normalized = normalizeChange(key, result[`${ADDITION_PREFIX}${key}`]); changes.push({ - key, - updated: result[`${ADDITION_PREFIX}${key}`], + key: normalized.key, + updated: normalized.value, }); } - return { result, changes }; + return { + result, + changes + }; }; 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 index 0709a5d9c41d6..922e593529283 100644 --- 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 @@ -16,7 +16,6 @@ import { EuiFieldNumber, EuiHorizontalRule, EuiCallOut, - EuiFormRow, EuiButtonEmpty, EuiIconTip, EuiLink, @@ -99,54 +98,45 @@ export class Configuration extends Component {

Configure options

- - - - Where do you want your hot indices to live -   - -
+ + Where do you want your hot indices to live +   + + + } + errorKey={STRUCTURE_NODE_ATTRS} + isShowingErrors={isShowingErrors} + errors={errors} + helpText={selectedNodeAttrs ? ( + + this.setState({ isShowingNodeDetailsFlyout: true }) } - errorKey={STRUCTURE_NODE_ATTRS} - isShowingErrors={isShowingErrors} - errors={errors} > - { - await setSelectedNodeAttrs(e.target.value); - validate(); - }} - options={nodeOptions} - /> - -
- {selectedNodeAttrs ? ( - - - - this.setState({ isShowingNodeDetailsFlyout: true }) - } - > - View node details - - - + View node details + ) : 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.{' '} - + Learn more.

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 index 8a5f80515d899..fb11120d37d3c 100644 --- 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 @@ -9,19 +9,33 @@ import { TemplateSelection as PresentationComponent } from './template_selection import { getIndexTemplateOptions, getSelectedIndexTemplateName, + getIndexName, + getAliasName, + getBootstrapEnabled, + getSelectedIndexTemplateIndices, } from '../../../../../../store/selectors'; import { fetchIndexTemplates, - setSelectedIndexTemplate + 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 index 808c0e1dc3caa..a158b406762d5 100644 --- 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 @@ -7,9 +7,13 @@ import React, { Fragment, PureComponent } from 'react'; import PropTypes from 'prop-types'; -import { EuiSelect } from '@elastic/eui'; +import { EuiSelect, EuiFormRow, EuiSwitch, EuiFieldText } from '@elastic/eui'; import { ErrableFormRow } from '../../../../form_errors'; -import { STRUCTURE_TEMPLATE_NAME } from '../../../../../../store/constants'; +import { + STRUCTURE_TEMPLATE_NAME, + STRUCTURE_INDEX_NAME, + STRUCTURE_ALIAS_NAME, +} from '../../../../../../store/constants'; export class TemplateSelection extends PureComponent { static propTypes = { @@ -31,31 +35,22 @@ export class TemplateSelection extends PureComponent { const { setSelectedIndexTemplate, validate, + setBootstrapEnabled, + setIndexName, + setAliasName, + bootstrapEnabled, templateOptions, + selectedIndexTemplateIndices, + indexName, + aliasName, 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} */} + {selectedIndexTemplateName && selectedIndexTemplateIndices.length === 0 ? ( + + + 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} + + ) : null} ); } 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 index 62d2c71597a8a..b80cbaf77d919 100644 --- 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 @@ -6,6 +6,7 @@ import React, { Fragment, Component } from 'react'; import PropTypes from 'prop-types'; +import { toastNotifications } from 'ui/notify'; import { TemplateSelection } from './components/template_selection'; import { Configuration } from './components/configuration'; @@ -48,6 +49,8 @@ export class IndexTemplate extends Component { this.setState({ isShowingErrors: true }); if (await this.validate()) { this.props.done(); + } else { + toastNotifications.addDanger('Please fix errors on the page.'); } }; @@ -65,7 +68,7 @@ export class IndexTemplate extends Component {
- A template defines the settings, mappings, and aliases to apply + An index template defines the settings, mappings, and aliases to apply when you create an index.
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 index 8887b13740e04..3128a38c2c34f 100644 --- 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 @@ -6,12 +6,13 @@ import { connect } from 'react-redux'; import { NodeAttrsDetails as PresentationComponent } from './node_attrs_details'; -import { getNodeDetails } from '../../../../store/selectors'; +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 index 0af37a84918a8..6bb03853e8f31 100644 --- 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { PureComponent } from 'react'; +import React, { Fragment, PureComponent } from 'react'; import PropTypes from 'prop-types'; import { @@ -25,6 +25,7 @@ export class NodeAttrsDetails extends PureComponent { details: PropTypes.array, selectedNodeAttrs: PropTypes.string.isRequired, + allocationRules: PropTypes.object, }; componentWillMount() { @@ -32,29 +33,28 @@ export class NodeAttrsDetails extends PureComponent { } render() { - const { selectedNodeAttrs, details, close } = this.props; + const { selectedNodeAttrs, allocationRules, details, close } = this.props; return ( -

- Below is a list of nodes that contain the attribute: `{ - selectedNodeAttrs - }` -

+

Nodes that contain the attribute: `{selectedNodeAttrs}`

- - Be aware that the nodes listed here only directly match the node - attribute string and other nodes might be affected by this policy - due to other allocation rules. - - + {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}

- This phase is optional. Re-allocate your indices again and - modify the number of replicas. + This phase is optional. Your read-only index is queried less frequently. + Use this phase when the index no longer needs to be on the most performant hardware.

@@ -172,37 +169,29 @@ export class ColdPhase extends PureComponent { - - - showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])} > - { - await setPhaseData(PHASE_NODE_ATTRS, e.target.value); - validate(); - }} - /> - - - {phaseData[PHASE_NODE_ATTRS] ? ( - - - showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])} - > - See more details about these nodes - - - + View node details + ) : null} - + > + { + await setPhaseData(PHASE_NODE_ATTRS, e.target.value); + validate(); + }} + /> + @@ -229,7 +218,7 @@ export class ColdPhase extends PureComponent { setPhaseData(PHASE_REPLICA_COUNT, warmPhaseReplicaCount) } > - Set to same as warm phase + Use number in warm phase 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 index 9b1998df49500..ed28165c9ccc5 100644 --- 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 @@ -86,8 +86,7 @@ export class DeletePhase extends PureComponent {

- This phase is optional. Delete your indices after a - configured amount of time. + This phase is optional. Your data is no longer useful. Define how long you want to retain it.

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 index 4111e11a31c4d..ca35b917b0e7c 100644 --- 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 @@ -4,9 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ - - - import React, { Fragment, PureComponent } from 'react'; import PropTypes from 'prop-types'; @@ -21,7 +18,8 @@ import { EuiAccordion, EuiFieldNumber, EuiSelect, - EuiSwitch + EuiSwitch, + EuiLink } from '@elastic/eui'; import { PHASE_ROLLOVER_ALIAS, @@ -93,7 +91,7 @@ export class HotPhase extends PureComponent { -

This phase is required. Rollover data by time and size.

+

This phase is required. Your index is being queried and in active writing mode.

{isShowingErrors ? ( @@ -111,7 +109,7 @@ export class HotPhase extends PureComponent { >
-

Rollover configuration

+

Rollover condition

+ + +

+ + Rollover the index when it gets too big or too old. The alias will switch to the new index. + +   + + Learn more. + +

+
{phaseData[PHASE_ROLLOVER_ENABLED] ? ( - {/* - - - { - showErrorsFor(PHASE_ROLLOVER_ALIAS); - setPhaseData(PHASE_ROLLOVER_ALIAS, e.target.value); - }} - /> - - - */}

- This phase is optional. Re-allocate indices, redefine number - of active shards, replicas, and compress even further. + This phase is optional. Your index is frequently queried, + but is read-only. Use this phase to optimize for search.

@@ -171,7 +173,7 @@ export class WarmPhase extends Component { { await this.setState({ applyOnRollover: e.target.checked }); @@ -222,37 +224,34 @@ export class WarmPhase extends Component { - - - - { - await setPhaseData(PHASE_NODE_ATTRS, e.target.value); - validate(); - }} - /> - - - {phaseData[PHASE_NODE_ATTRS] ? ( - - - showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])} - > - See more details about these nodes - - - - ) : null} - + + showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS]) + } + > + View node details + + ) : null + } + > + { + await setPhaseData(PHASE_NODE_ATTRS, e.target.value); + validate(); + }} + /> + + - Set to same as hot phase + Use number in hot phase @@ -293,56 +292,89 @@ export class WarmPhase extends Component {

Shrink

+ + + Shrink the index into a new index with fewer primary shards.{' '} + + Learn more. + + + - - - - { - await setPhaseData( - PHASE_PRIMARY_SHARD_COUNT, - e.target.value - ); - validate(); - }} - /> - - - - - { - await setPhaseData( - PHASE_PRIMARY_SHARD_COUNT, - hotPhasePrimaryShardCount - ); - validate(); - }} - > - Set to same as hot phase - - - - + { + await setPhaseData(PHASE_SHRINK_ENABLED, e.target.checked); + validate(); + }} + label="Enable shrink" + /> - + + + {phaseData[PHASE_SHRINK_ENABLED] ? ( + + + + + { + await setPhaseData( + PHASE_PRIMARY_SHARD_COUNT, + e.target.value + ); + validate(); + }} + /> + + + + + { + await setPhaseData( + PHASE_PRIMARY_SHARD_COUNT, + hotPhasePrimaryShardCount + ); + validate(); + }} + > + Use number in hot phase + + + + + + + + ) : null}

Force merge

+ + + Reduce the number of segments in your shard by and merging smaller + files and clearing deleted ones.{' '} + + Learn More + + + + { await setPhaseData(PHASE_FORCE_MERGE_ENABLED, e.target.checked); @@ -352,20 +384,25 @@ export class WarmPhase extends Component { - - { - await setPhaseData(PHASE_FORCE_MERGE_SEGMENTS, e.target.value); - validate(); - }} - /> - + {phaseData[PHASE_FORCE_MERGE_ENABLED] ? ( + + { + await setPhaseData( + PHASE_FORCE_MERGE_SEGMENTS, + e.target.value + ); + validate(); + }} + /> + + ) : null}
); 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 index a64806993fb5c..29da1a719d9b5 100644 --- 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 @@ -4,9 +4,6 @@ * 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 { @@ -17,7 +14,8 @@ import { getIndexName, getAliasName, getSaveAsNewPolicy, - getSelectedOriginalPolicyName + getSelectedOriginalPolicyName, + getIsSelectedPolicySet } from '../../../../store/selectors'; import { setBootstrapEnabled, @@ -29,6 +27,7 @@ import { export const PolicyConfiguration = connect( state => ({ + isSelectedPolicySet: getIsSelectedPolicySet(state), selectedPolicyName: getSelectedPolicyName(state), selectedIndexTemplateName: getSelectedIndexTemplateName(state), affectedIndexTemplates: getAffectedIndexTemplates(state), 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 index 29ef2b1c5cfb4..df1c4199ab507 100644 --- 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 @@ -4,18 +4,15 @@ * 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 PropTypes from 'prop-types'; +import { toastNotifications } from 'ui/notify'; import { EuiTitle, EuiSpacer, - EuiCallOut, EuiHorizontalRule, EuiButton, - EuiFormRow, - EuiSwitch, - EuiFieldText, EuiButtonEmpty, } from '@elastic/eui'; import { HotPhase } from './components/hot_phase'; @@ -27,13 +24,10 @@ import { 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'; import { NodeAttrsDetails } from '../node_attrs_details'; +import { PolicySelection } from '../policy_selection/policy_selection.container'; export class PolicyConfiguration extends Component { static propTypes = { @@ -76,6 +70,8 @@ export class PolicyConfiguration extends Component { this.setState({ isShowingErrors: true }); if (await this.validate()) { this.props.done(); + } else { + toastNotifications.addDanger('Please fix errors on the page.'); } }; @@ -85,62 +81,55 @@ export class PolicyConfiguration extends Component { render() { const { - setSelectedPolicyName, - setSaveAsNewPolicy, - setBootstrapEnabled, - setIndexName, - setAliasName, - validate, back, - affectedIndexTemplates, - selectedIndexTemplateName, selectedPolicyName, - saveAsNewPolicy, + isSelectedPolicySet, errors, - bootstrapEnabled, - indexName, - aliasName, - originalPolicyName, } = this.props; const { isShowingErrors } = this.state; - const singleTemplate = ( - - This policy is only attached to the selected template{' '} - {selectedIndexTemplateName}. - - ); + if (!isSelectedPolicySet) { + return ( + + ); + } - const multiTemplate = ( - - This policy is attached to{' '} - {affectedIndexTemplates.length - 1} other template(s){' '} - besides {selectedIndexTemplateName}. - - ); + // 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; + // const warningMessage = + // affectedIndexTemplates.length === 1 && + // affectedIndexTemplates[0] === selectedIndexTemplateName + // ? singleTemplate + // : multiTemplate; return (
+ + -

Edit policy: {selectedPolicyName}

+

+ {!selectedPolicyName ? 'Edit new policy' : `Edit policy ${selectedPolicyName}`} +

+
+ + +
Configure the phases of your data and when to transition between them. Only the hot phase is required.
- - - Only the hot phase is required. - - } - /> - + {/* @@ -248,9 +237,9 @@ export class PolicyConfiguration extends Component { ) : null} - + */} - + {/* */} -

Select a policy to start from

+

Select a policy

- You can edit existing policies and save them under a new name - later + An index lifecycle policy is a blueprint for transitioning your data over time. + You can create a new policy or edit an existing policy and save it with a new name.

@@ -90,15 +85,15 @@ export class PolicySelection extends Component { ))} - + {/* */} - Back - +
*/}
); } 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 index 27d206d1f797b..77809dc140e53 100644 --- 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 @@ -22,7 +22,7 @@ import { mergeAndPreserveDuplicateKeys, removePrefixes, } from '../../../../lib/diff_tools'; -import { addDiffAddonsForAce } from '../../../../lib/diff_ace_addons'; +import { addDiffAddonsForAce, setCurrentJsonObject } from '../../../../lib/diff_ace_addons'; export class DiffView extends PureComponent { static propTypes = { @@ -35,8 +35,11 @@ export class DiffView extends PureComponent { scrollToKey = (key, value) => { const editorDom = this.aceEditor.aceEditor.refEditor; const editor = ace.edit(editorDom); - const escapedValue = value.replace(/\^/, '\\^'); + 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); } @@ -52,14 +55,17 @@ export class DiffView extends PureComponent { newFullIndexTemplate ); - // console.log('mergedJson', mergedJson, changes); + console.log('mergedJson', mergedJson, changes); // Strip the ^ and $ characters const mergedJsonAsString = removePrefixes( JSON.stringify(mergedJson, null, 2) ); - addDiffAddonsForAce(mergedJson); + // console.log('mergedJsonAsString', mergedJsonAsString); + + setCurrentJsonObject(mergedJson); + addDiffAddonsForAce(); return ( @@ -75,10 +81,10 @@ export class DiffView extends PureComponent { {original ? ( - Changing `{original}` to `{updated}`` + Changing `{JSON.stringify(original)}` to `{JSON.stringify(updated)}`` ) : ( - Adding with `{updated}` + Adding with `{JSON.stringify(updated)}` )} 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 index a809576f77dd9..6c4ee3b274347 100644 --- 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 @@ -19,10 +19,14 @@ import { getSelectedOriginalPolicyName, getAliasName, getBootstrapEnabled, + getIndexName, } from '../../../../store/selectors'; import { setSelectedPolicyName, setSaveAsNewPolicy, + setAliasName, + setIndexName, + setBootstrapEnabled, } from '../../../../store/actions'; export const Review = connect( @@ -33,13 +37,19 @@ export const Review = connect( lifecycle: getLifecycle(state), bootstrapEnabled: getBootstrapEnabled(state), aliasName: getAliasName(state), - selectedIndexTemplateName: getSelectedIndexTemplateName(state), selectedPolicyName: getSelectedPolicyName(state), saveAsNewPolicy: getSaveAsNewPolicy(state), originalPolicyName: getSelectedOriginalPolicyName(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 index 66c54a738142f..5c61331258f9f 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 @@ -6,6 +6,7 @@ import React, { Fragment, Component } from 'react'; import PropTypes from 'prop-types'; +import { toastNotifications } from 'ui/notify'; // import DiffEditor from 'react-ace/lib/diff'; import './review.less'; @@ -24,10 +25,17 @@ import { EuiFlexGrid, EuiPanel, EuiText, - EuiButtonEmpty + EuiButtonEmpty, + EuiFormRow, + EuiSwitch, + EuiFieldText, + EuiLoadingSpinner, } 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 = { @@ -52,22 +60,68 @@ export class Review extends Component { this.state = { selectedTab: 1, affectedIndices: [], + isLoadingAffectedIndices: false, }; + + this.currentFetchTimeout = null; + } + + 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 }); + }, 500); } async componentWillMount() { - const affectedIndices = await getAffectedIndices( - this.props.selectedIndexTemplateName, - this.props.selectedPolicyName - ); - this.setState({ affectedIndices }); + 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 errors on the page.'); + } + }; + render() { const { done, back, + /* Start might move */ + setSelectedPolicyName, + setSaveAsNewPolicy, + validate, + + errors, + selectedPolicyName, + saveAsNewPolicy, + originalPolicyName, + /* End might move */ + selectedIndexTemplateName, affectedIndexTemplates, templateDiff, @@ -76,25 +130,62 @@ export class Review extends Component { aliasName, } = this.props; - const { affectedIndices } = this.state; + const { affectedIndices, isLoadingAffectedIndices, isShowingErrors } = this.state; + + // console.log('render', affectedIndices); return (
- + {/*

Changes that will occur

+ */} + + + {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} + + -

{affectedIndexTemplates.length}

+

{affectedIndexTemplates.length} Affected Index {affectedIndexTemplates.length === 1 ? 'Template' : 'Templates' }

-

- Index templates affected by this change (to - the selected policy): -

    {affectedIndexTemplates.map(template => (
  • {template}
  • @@ -106,16 +197,16 @@ export class Review extends Component { -

    {affectedIndices.length}

    +

    {affectedIndices.length} Affected {affectedIndices.length === 1 ? 'Index' : 'Indices' }

    -

    - Indices affected by this change (to the - selected policy): -

    -
      - {affectedIndices.map(index =>
    • {index}
    • )} -
    + { isLoadingAffectedIndices ? ( + + ) : ( +
      + {affectedIndices.map(index =>
    • {index}
    • )} +
    + ) }
    @@ -177,7 +268,7 @@ export class Review extends Component { iconType="check" onClick={() => done(lifecycle)} > - Looks good, make these changes + Looks good, save changes
); diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json index 0411f08b735f4..9ce2e9b307baa 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json @@ -1,284 +1,33 @@ { "originalFullIndexTemplate": { - "@elastic/eui": "v0.0.44", - "@elastic/filesaver": "1.1.2", - "@elastic/numeral": "2.3.2", - "@elastic/ui-ace": "0.2.3", - "@kbn/babel-preset": "link:packages/kbn-babel-preset", - "@kbn/datemath": "link:packages/kbn-datemath", - "@kbn/pm": "link:packages/kbn-pm", - "@kbn/test-subj-selector": "link:packages/kbn-test-subj-selector", - "@kbn/ui-framework": "link:packages/kbn-ui-framework", - "JSONStream": "1.1.1", - "accept-language-parser": "1.2.0", - "angular": "1.6.9", - "angular-aria": "1.6.6", - "angular-elastic": "2.5.0", - "angular-recursion": "^1.0.5", - "angular-route": "1.4.7", - "angular-sanitize": "1.5.7", - "angular-sortable-view": "0.0.15", - "autoprefixer": "6.5.4", - "babel-core": "6.21.0", - "babel-loader": "7.1.2", - "babel-polyfill": "6.20.0", - "babel-register": "6.18.0", - "bluebird": "2.9.34", - "body-parser": "1.12.0", - "boom": "5.2.0", - "brace": "0.10.0", - "bunyan": "1.7.1", - "cache-loader": "1.0.3", - "chalk": "2.3.0", - "check-hash": "1.0.1", - "color": "1.0.3", - "commander": "2.8.1", - "compare-versions": "3.1.0", - "css-loader": "0.28.7", - "custom-event-polyfill": "^0.3.0", - "d3": "3.5.6", - "d3-cloud": "1.2.1", - "dragula": "3.7.0", - "elasticsearch": "^14.2.1", - "elasticsearch-browser": "^14.2.1", - "encode-uri-query": "1.0.0", - "even-better": "7.0.2", - "expiry-js": "0.1.7", - "extract-text-webpack-plugin": "3.0.1", - "file-loader": "1.1.4", - "font-awesome": "4.4.0", - "glob": "5.0.13", - "glob-all": "3.0.1", - "good-squeeze": "2.1.0", - "h2o2": "5.1.1", - "handlebars": "4.0.5", - "hapi": "14.2.0", - "hjson": "3.1.0", - "http-proxy-agent": "1.0.0", - "https-proxy-agent": "2.1.1", - "inert": "4.0.2", - "jade": "1.11.0", - "jade-loader": "0.8.0", - "joi": "10.4.1", - "jquery": "^3.3.1", - "js-yaml": "3.4.1", - "json-stringify-pretty-compact": "1.0.4", - "json-stringify-safe": "5.0.1", - "jstimezonedetect": "1.0.5", - "leaflet": "1.0.3", - "leaflet-draw": "0.4.10", - "leaflet-responsive-popup": "0.2.0", - "leaflet-vega": "^0.8.6", - "leaflet.heat": "0.2.0", - "less": "2.7.1", - "less-loader": "4.0.5", - "lodash": "3.10.1", - "lru-cache": "4.1.1", - "markdown-it": "8.3.2", - "minimatch": "2.0.10", - "mkdirp": "0.5.1", - "moment": "^2.20.1", - "moment-timezone": "^0.5.14", - "mustache": "2.3.0", - "ngreact": "0.5.1", - "no-ui-slider": "1.2.0", - "node-fetch": "1.3.2", - "pegjs": "0.9.0", - "postcss-loader": "2.0.6", - "prop-types": "15.5.8", - "proxy-from-env": "1.0.0", - "querystring-browser": "1.0.4", - "raw-loader": "0.5.1", - "react": "^16.2.0", - "react-addons-shallow-compare": "15.6.2", - "react-anything-sortable": "^1.7.4", - "react-color": "^2.13.8", - "react-dom": "^16.2.0", - "react-grid-layout": "^0.16.2", - "react-input-range": "^1.3.0", - "react-markdown": "^3.1.4", - "react-redux": "^5.0.6", - "react-router-dom": "4.2.2", - "react-select": "^1.2.0", - "react-sizeme": "^2.3.6", - "react-toggle": "4.0.2", - "reactcss": "1.2.3", - "redux": "3.7.2", - "redux-actions": "2.2.1", - "redux-thunk": "2.2.0", - "regression": "2.0.0", - "request": "^2.85.0", - "reselect": "^3.0.1", - "resize-observer-polyfill": "1.2.1", - "rimraf": "2.4.3", - "rison-node": "1.0.0", - "rxjs": "5.4.3", - "script-loader": "0.7.2", - "semver": "5.1.0", - "style-loader": "0.19.0", - "tar": "2.2.0", - "tinygradient": "0.3.0", - "tinymath": "0.2.1", - "topojson-client": "3.0.0", - "trunc-html": "1.0.2", - "trunc-text": "1.0.2", - "uglifyjs-webpack-plugin": "0.4.6", - "ui-select": "0.19.6", - "url-loader": "0.5.9", - "uuid": "3.0.1", - "validate-npm-package-name": "2.2.2", - "vega-lib": "^3.3.1", - "vega-lite": "^2.4.0", - "vega-tooltip": "^0.9.14", - "vega-schema-url-parser": "1.0.0", - "vision": "4.1.0", - "webpack": "3.6.0", - "webpack-merge": "4.1.0", - "whatwg-fetch": "^2.0.3", - "wreck": "12.4.0", - "x-pack": "link:x-pack", - "yauzl": "2.7.0" + "settings": { + "index": { + "number_of_shards": "1", + "auto_expand_replicas": "0-1", + "lifecycle": { + "name": "my_policy" + } + } + } }, "newFullIndexTemplate": { - "@elastic/eui": "v0.0.44", - "@elastic/filesaver": "1.1.2", - "@elastic/numeral": "2.3.2", - "@elastic/ui-ace": "0.2.3", - "@kbn/babel-preset": "link:packages/kbn-babel-preset", - "@kbn/datemath": "link:packages/kbn-datemath", - "@kbn/pm": "link:packages/kbn-pm", - "@kbn/test-subj-selector": "link:packages/kbn-test-subj-selector", - "@kbn/ui-framework": "link:packages/kbn-ui-framework", - "JSONStream": "1.1.1", - "accept-language-parser": "1.2.0", - "angular": "1.6.9", - "angular-aria": "1.6.6", - "angular-elastic": "2.5.0", - "angular-recursion": "^1.0.5", - "angular-route": "1.4.7", - "angular-sanitize": "1.5.7", - "angular-sortable-view": "0.0.15", - "autoprefixer": "6.5.4", - "babel-core": "6.21.0", - "babel-loader": "7.1.2", - "babel-polyfill": "6.20.0", - "babel-register": "6.18.0", - "bluebird": "2.9.34", - "body-parser": "1.12.0", - "boom": "5.2.0", - "brace": "0.10.0", - "bunyan": "1.7.1", - "cache-loader": "1.0.3", - "chalk": "2.3.0", - "check-hash": "1.0.1", - "color": "1.0.3", - "commander": "2.8.1", - "compare-versions": "3.1.0", - "css-loader": "0.28.7", - "custom-event-polyfill": "^0.3.0", - "d3": "3.5.6", - "d3-cloud": "1.2.1", - "dragula": "3.7.0", - "elasticsearch": "^14.2.1", - "elasticsearch-browser": "^14.2.1", - "encode-uri-query": "1.0.0", - "even-better": "7.0.2", - "expiry-js": "0.1.7", - "extract-text-webpack-plugin": "3.0.1", - "file-loader": "1.1.4", - "font-awesome": "4.4.0", - "glob": "5.0.13", - "glob-all": "3.0.1", - "good-squeeze": "2.1.0", - "h2o2": "5.1.1", - "handlebars": "4.0.5", - "hapi": "14.2.0", - "hjson": "3.1.0", - "http-proxy-agent": "1.0.0", - "https-proxy-agent": "2.1.1", - "inert": "4.0.2", - "jade": "1.11.0", - "jade-loader": "0.8.0", - "joi": "10.4.1", - "jquery": "^3.3.1", - "js-yaml": "3.4.1", - "json-stringify-pretty-compact": "1.0.4", - "json-stringify-safe": "5.0.1", - "jstimezonedetect": "1.0.5", - "leaflet": "1.0.3", - "leaflet-draw": "0.4.10", - "leaflet-responsive-popup": "0.2.0", - "leaflet-vega": "^0.8.6", - "leaflet.heat": "0.2.0", - "less": "2.7.1", - "less-loader": "4.0.5", - "lodash": "3.10.1", - "lru-cache": "4.1.1", - "markdown-it": "8.3.2", - "minimatch": "2.0.10", - "mkdirp": "0.5.1", - "moment": "^2.20.1", - "moment-timezone": "^0.5.14", - "mustache": "2.3.0", - "ngreact": "0.5.1", - "no-ui-slider": "1.2.0", - "node-fetch": "1.3.2", - "pegjs": "0.9.0", - "postcss-loader": "2.0.6", - "prop-types": "15.5.8", - "proxy-from-env": "1.0.0", - "querystring-browser": "1.0.4", - "raw-loader": "0.5.1", - "react": "^16.3.0", - "react-addons-shallow-compare": "15.6.2", - "react-anything-sortable": "^1.7.4", - "react-color": "^2.13.8", - "react-dom": "^16.3.0", - "react-grid-layout": "^0.16.2", - "react-input-range": "^1.3.0", - "react-markdown": "^3.1.4", - "react-redux": "^5.0.6", - "react-router-dom": "4.2.2", - "react-select": "^1.2.0", - "react-sizeme": "^2.3.6", - "react-toggle": "4.0.2", - "reactcss": "1.2.3", - "redux": "3.7.2", - "redux-actions": "2.2.1", - "redux-thunk": "2.2.0", - "regression": "2.0.0", - "request": "^2.85.0", - "reselect": "^3.0.1", - "resize-observer-polyfill": "1.2.1", - "rimraf": "2.4.3", - "rison-node": "1.0.0", - "rxjs": "5.4.3", - "script-loader": "0.7.2", - "semver": "5.1.0", - "style-loader": "0.19.0", - "tar": "2.2.0", - "tinygradient": "0.3.0", - "tinymath": "0.2.1", - "topojson-client": "3.0.0", - "trunc-html": "1.0.2", - "trunc-text": "1.0.2", - "uglifyjs-webpack-plugin": "0.4.6", - "ui-select": "0.19.6", - "url-loader": "0.5.9", - "uuid": "3.0.2", - "validate-npm-package-name": "2.2.2", - "vega-lib": "^3.3.1", - "vega-lite": "^2.4.0", - "vega-tooltip": "^0.9.14", - "vega-schema-url-parser": "1.0.0", - "vision": "4.1.0", - "webpack": "3.6.0", - "webpack-merge": "4.1.0", - "whatwg-fetch": "^2.0.3", - "wreck": "12.4.0", - "x-pack": "link:x-pack", - "yauzl": "2.7.0", - "zzz": "1.0.0" + "settings": { + "index": { + "number_of_shards": "1", + "auto_expand_replicas": "0-1", + "number_of_replicas": "1", + "lifecycle": { + "name": "my_policy4" + }, + "routing": { + "allocation": { + "include": { + "sattr_name": "node" + } + } + } + } + } }, "hasChanged": true } 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 index 9a73050b124ff..63d6a7c00a83e 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js @@ -8,7 +8,7 @@ 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 { PolicySelection } from './components/policy_selection'; import { PolicyConfiguration } from './components/policy_configuration'; import { Review } from './components/review'; import { @@ -23,6 +23,7 @@ import { bootstrap } from '../../api'; import { STRUCTURE_INDEX_TEMPLATE, STRUCTURE_POLICY_CONFIGURATION, + STRUCTURE_REVIEW, } from '../../store/constants'; // import { DiffView } from './components/review/diff_view'; // import diff from './diff.json'; @@ -99,27 +100,29 @@ export class Wizard extends Component { done={() => this.onSelectedStepChanged(2)} /> ); + // case 2: + // return ( + // this.onSelectedStepChanged(3)} + // back={() => this.onSelectedStepChanged(1)} + // /> + // ); case 2: - return ( - this.onSelectedStepChanged(3)} - back={() => this.onSelectedStepChanged(1)} - /> - ); - case 3: return ( this.onSelectedStepChanged(4)} - back={() => this.onSelectedStepChanged(2)} + done={() => this.onSelectedStepChanged(3)} + back={() => this.onSelectedStepChanged(1)} /> ); - case 4: + case 3: return ( this.onSelectedStepChanged(3)} + errors={errors[STRUCTURE_REVIEW]} + back={() => this.onSelectedStepChanged(2)} /> ); } @@ -133,27 +136,27 @@ export class Wizard extends Component { 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: 'Select or create policy', + title: 'Configure policy', isSelected: this.state.selectedStep === 2, isComplete: this.state.selectedStep > 2, disabled: this.state.selectedStep < 2, onClick: () => this.onSelectedStepChanged(2), }, { - title: 'Configure policy', + title: 'Review and save', 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), - }, ]; // const templateDiff = diff; @@ -171,7 +174,7 @@ export class Wizard extends Component { {/* */} {this.renderContent()} 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 7b6e7076d87c5..04c59709bd426 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/constants.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/constants.js @@ -29,6 +29,8 @@ export const PHASE_ROLLOVER_AFTER_UNITS = 'selectedAfterUnits'; export const PHASE_FORCE_MERGE_SEGMENTS = 'selectedForceMergeSegments'; export const PHASE_FORCE_MERGE_ENABLED = 'forceMergeEnabled'; +export const PHASE_SHRINK_ENABLED = 'shrinkEnabled'; + export const PHASE_NODE_ATTRS = 'selectedNodeAttrs'; export const PHASE_PRIMARY_SHARD_COUNT = 'selectedPrimaryShardCount'; export const PHASE_REPLICA_COUNT = 'selectedReplicaCount'; @@ -52,6 +54,8 @@ export const STRUCTURE_PRIMARY_NODES = 'primary_nodes'; export const STRUCTURE_REPLICAS = 'replicas'; export const STRUCTURE_POLICY_CONFIGURATION = 'policyConfiguration'; + +export const STRUCTURE_REVIEW = 'review'; export const STRUCTURE_POLICY_NAME = 'policyName'; export const STRUCTURE_INDEX_NAME = 'indexName'; export const STRUCTURE_ALIAS_NAME = 'aliasName'; @@ -59,7 +63,9 @@ export const STRUCTURE_ALIAS_NAME = 'aliasName'; export const ERROR_STRUCTURE = { [STRUCTURE_INDEX_TEMPLATE]: { [STRUCTURE_TEMPLATE_SELECTION]: { - [STRUCTURE_TEMPLATE_NAME]: [] + [STRUCTURE_TEMPLATE_NAME]: [], + [STRUCTURE_INDEX_NAME]: [], + [STRUCTURE_ALIAS_NAME]: [] }, [STRUCTURE_CONFIGURATION]: { [STRUCTURE_NODE_ATTRS]: [], @@ -68,9 +74,6 @@ export const ERROR_STRUCTURE = { } }, [STRUCTURE_POLICY_CONFIGURATION]: { - [STRUCTURE_POLICY_NAME]: [], - [STRUCTURE_INDEX_NAME]: [], - [STRUCTURE_ALIAS_NAME]: [], [PHASE_HOT]: { [PHASE_ROLLOVER_ALIAS]: [], [PHASE_ROLLOVER_MAX_AGE]: [], @@ -100,5 +103,8 @@ export const ERROR_STRUCTURE = { [PHASE_ROLLOVER_AFTER]: [], [PHASE_ROLLOVER_AFTER_UNITS]: [], }, + }, + [STRUCTURE_REVIEW]: { + [STRUCTURE_POLICY_NAME]: [], } }; 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 8b68c8a5d1ceb..7a44e98db113b 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 @@ -36,7 +36,8 @@ import { PHASE_ROLLOVER_MAX_SIZE_STORED, PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS, PHASE_ROLLOVER_ALIAS, - PHASE_ROLLOVER_MAX_DOC_SIZE + PHASE_ROLLOVER_MAX_DOC_SIZE, + PHASE_SHRINK_ENABLED } from '../constants'; export const defaultWarmPhase = { @@ -48,6 +49,7 @@ export const defaultWarmPhase = { [PHASE_ROLLOVER_AFTER]: '', [PHASE_ROLLOVER_AFTER_UNITS]: 's', [PHASE_NODE_ATTRS]: '', + [PHASE_SHRINK_ENABLED]: true, [PHASE_PRIMARY_SHARD_COUNT]: '', [PHASE_REPLICA_COUNT]: '' }; @@ -95,6 +97,7 @@ const defaultPolicy = { const defaultState = { isLoading: false, originalPolicyName: undefined, + selectedPolicySet: false, selectedPolicy: defaultPolicy, policies: [] }; @@ -113,12 +116,14 @@ export const policies = handleActions( return { ...state, selectedPolicy: defaultPolicy, + selectedPolicySet: true, }; } return { ...state, originalPolicyName: selectedPolicy.name, + selectedPolicySet: true, selectedPolicy: { ...defaultPolicy, ...policyFromES(selectedPolicy) 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 38947e3f475f1..c99fb716e4761 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 @@ -112,7 +112,23 @@ export const getAffectedIndexPatterns = state => { return indexPatterns; }; -// const hasJSONChanged = (json1, json2) => JSON.stringify(json1) !== JSON.stringify(json2); +export const getSelectedIndexTemplateIndices = state => { + const selectedIndexTemplate = getSelectedIndexTemplate(state); + if (selectedIndexTemplate) { + return selectedIndexTemplate.indices; + } + return undefined; +}; + +export const getExistingAllocationRules = state => { + const selectedIndexTemplate = getSelectedIndexTemplate(state); + if (selectedIndexTemplate) { + return selectedIndexTemplate.allocation_rules; + } + return undefined; +}; + +const hasJSONChanged = (json1, json2) => JSON.stringify(json1) !== JSON.stringify(json2); export const getTemplateDiff = state => { const originalFullIndexTemplate = getFullSelectedIndexTemplate(state) || { settings: {} }; const newFullIndexTemplate = merge(cloneDeep(originalFullIndexTemplate), { @@ -137,7 +153,7 @@ export const getTemplateDiff = state => { return { originalFullIndexTemplate, newFullIndexTemplate, - hasChanged: true//hasJSONChanged(originalFullIndexTemplate, newFullIndexTemplate), + hasChanged: hasJSONChanged(originalFullIndexTemplate, newFullIndexTemplate), }; }; 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 235ebb4dd2062..a34e94af5c6ab 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 @@ -4,9 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ - - - import { PHASE_HOT, PHASE_WARM, @@ -18,7 +15,6 @@ import { PHASE_ROLLOVER_MAX_SIZE_STORED, STRUCTURE_INDEX_TEMPLATE, STRUCTURE_CONFIGURATION, - STRUCTURE_NODE_ATTRS, STRUCTURE_PRIMARY_NODES, STRUCTURE_REPLICAS, STRUCTURE_TEMPLATE_SELECTION, @@ -28,7 +24,10 @@ import { STRUCTURE_INDEX_NAME, STRUCTURE_ALIAS_NAME, ERROR_STRUCTURE, - PHASE_ATTRIBUTES_THAT_ARE_NUMBERS + PHASE_ATTRIBUTES_THAT_ARE_NUMBERS, + PHASE_PRIMARY_SHARD_COUNT, + PHASE_SHRINK_ENABLED, + STRUCTURE_REVIEW } from '../constants'; import { getPhase, @@ -37,7 +36,6 @@ import { getSelectedPolicyName, getSelectedIndexTemplateName, isNumber, - getSelectedNodeAttrs, getSelectedPrimaryShardCount, getSelectedReplicaCount, getSaveAsNewPolicy, @@ -69,12 +67,19 @@ export const validatePhase = (type, phase) => { } for (const numberedAttribute of PHASE_ATTRIBUTES_THAT_ARE_NUMBERS) { - if (phase.hasOwnProperty(numberedAttribute) && !phase[numberedAttribute] === '') { + if (phase.hasOwnProperty(numberedAttribute) && phase[numberedAttribute] !== '') { + // If shrink is disabled, there is no need to validate this + if (numberedAttribute === PHASE_PRIMARY_SHARD_COUNT && !phase[PHASE_SHRINK_ENABLED]) { + continue; + } if (!isNumber(phase[numberedAttribute])) { - errors[numberedAttribute].push('A number is required.'); + errors[numberedAttribute] = ['A number is required.']; } else if (phase[numberedAttribute] < 0) { - errors[numberedAttribute].push('Only positive numbers allowed.'); + errors[numberedAttribute] = ['Only positive numbers allowed.']; + } + else if (numberedAttribute === PHASE_PRIMARY_SHARD_COUNT && phase[numberedAttribute] < 1) { + errors[numberedAttribute] = ['Only positive numbers above 0 are allowed.']; } } } @@ -89,13 +94,15 @@ export const validateLifecycle = state => { if (!getSelectedIndexTemplateName(state)) { errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][ STRUCTURE_TEMPLATE_NAME - ].push('An index template is required.'); + ].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 (getBootstrapEnabled(state) && !getIndexName(state)) { + errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][STRUCTURE_INDEX_NAME].push('An index name is required.'); + } + + if (getBootstrapEnabled(state) && !getAliasName(state)) { + errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][STRUCTURE_ALIAS_NAME].push('An alias name is required.'); } if (!isNumber(getSelectedPrimaryShardCount(state))) { @@ -103,10 +110,10 @@ export const validateLifecycle = state => { STRUCTURE_PRIMARY_NODES ].push('A value is required.'); } - else if (getSelectedPrimaryShardCount(state) < 0) { + else if (getSelectedPrimaryShardCount(state) < 1) { errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][ STRUCTURE_PRIMARY_NODES - ].push('Only positive numbers allowed.'); + ].push('Only positive numbers above 0 are allowed.'); } if (!isNumber(getSelectedReplicaCount(state))) { @@ -121,11 +128,11 @@ export const validateLifecycle = state => { } if (!getSelectedPolicyName(state)) { - errors[STRUCTURE_POLICY_CONFIGURATION][STRUCTURE_POLICY_NAME].push('A policy name is required.'); + errors[STRUCTURE_REVIEW][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.'); + errors[STRUCTURE_REVIEW][STRUCTURE_POLICY_NAME].push('The policy name must be different.'); } // if (getSaveAsNewPolicy(state)) { @@ -135,14 +142,6 @@ export const validateLifecycle = state => { // } // } - 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)) 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 f0818f043ca94..94439f27c72a2 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 @@ -39,6 +39,7 @@ import { getIndexTemplates } from '.'; export const getPolicies = state => state.policies.policies; export const getSelectedPolicy = state => state.policies.selectedPolicy; +export const getIsSelectedPolicySet = state => state.policies.selectedPolicySet; export const getSelectedOriginalPolicyName = state => state.policies.originalPolicyName; export const getSaveAsNewPolicy = state => 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 73541518350f7..0cb74ac6d2599 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 @@ -38,7 +38,7 @@ async function getAffectedIndices( template.settings && template.settings.index && template.settings.index.lifecycle && - template.settings.index.lifecycle.name === policyName + (policyName && template.settings.index.lifecycle.name === policyName) ) { accum.push(...template.index_patterns); } @@ -64,6 +64,32 @@ export function registerGetAffectedRoute(server) { const isEsError = isEsErrorFactory(server); const licensePreRouting = licensePreRoutingFactory(server); + server.route({ + path: + '/api/index_lifecycle_management/indices/affected/{indexTemplateName}', + method: 'GET', + handler: async (request, reply) => { + const callWithRequest = callWithRequestFactory(server, request); + + try { + const response = await getAffectedIndices( + callWithRequest, + request.params.indexTemplateName, + ); + reply(response); + } catch (err) { + if (isEsError(err)) { + return reply(wrapEsError(err)); + } + + reply(wrapUnknownError(err)); + } + }, + config: { + pre: [licensePreRouting] + } + }); + server.route({ path: '/api/index_lifecycle_management/indices/affected/{indexTemplateName}/{policyName}', 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 37d15cf60a477..7bc4922478be0 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 @@ -20,6 +20,7 @@ async function formatTemplates(templates, callWithRequest) { const formattedTemplate = { index_lifecycle_name: settings.index && settings.index.lifecycle ? settings.index.lifecycle.name : undefined, index_patterns, + allocation_rules: settings.index && settings.index.routing ? settings.index.routing : undefined, name: templateName, }; From 4851068c49264d93732277c5172b750ce0695054 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 14 May 2018 11:58:48 -0400 Subject: [PATCH 09/62] Add logic to auto enable a phase when something is set --- .../store/middleware/auto_enable_phase.js | 29 +++++++++++++++++++ .../public/store/middleware/index.js | 7 +++++ .../public/store/reducers/policies.js | 2 +- .../public/store/store.js | 3 +- 4 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/middleware/auto_enable_phase.js create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/middleware/index.js 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 new file mode 100644 index 0000000000000..738be1fd7a56d --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/store/middleware/auto_enable_phase.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 { + setPhaseData +} from '../actions'; +import { getPhaseData } from '../selectors'; +import { PHASE_ENABLED } from '../constants'; + +const setsPerPhase = {}; + +export const autoEnablePhase = store => next => action => { + const state = store.getState(); + + if (action.type === setPhaseData().type) { + 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/index.js b/x-pack/plugins/index_lifecycle_management/public/store/middleware/index.js new file mode 100644 index 0000000000000..ccad9cac1daa4 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/store/middleware/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 { autoEnablePhase } from './auto_enable_phase'; 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 7a44e98db113b..91e6e255e0859 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 @@ -83,7 +83,7 @@ export const defaultDeletePhase = { [PHASE_ROLLOVER_AFTER_UNITS]: 's' }; -const defaultPolicy = { +export const defaultPolicy = { name: '', saveAsNew: true, phases: { 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 3566efa9fff10..355a834188f3f 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/store.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/store.js @@ -8,9 +8,10 @@ import { createStore, applyMiddleware, compose } from 'redux'; import thunk from 'redux-thunk'; import { indexLifecycleManagement } from './reducers/'; +import { autoEnablePhase } from './middleware'; export const indexLifecycleManagementStore = (initialState = {}) => { - const enhancers = [ applyMiddleware(thunk) ]; + const enhancers = [ applyMiddleware(thunk, autoEnablePhase) ]; window.__REDUX_DEVTOOLS_EXTENSION__ && enhancers.push(window.__REDUX_DEVTOOLS_EXTENSION__()); return createStore( From 5ca7b4f30ebc044e1665996ef74d90a36f65717b Mon Sep 17 00:00:00 2001 From: Dave Snider Date: Wed, 16 May 2018 14:14:46 -0700 Subject: [PATCH 10/62] redesign ilm --- package.json | 2 +- x-pack/package.json | 2 +- .../public/less/main.less | 49 ++ .../public/main.html | 2 +- .../components/configuration/configuration.js | 180 ++++--- .../template_selection/template_selection.js | 29 +- .../index_template/index_template.js | 28 +- .../node_attrs_details/node_attrs_details.js | 75 +-- .../components/cold_phase/cold_phase.js | 279 ++++++----- .../components/delete_phase/delete_phase.js | 179 +++---- .../components/hot_phase/hot_phase.js | 277 +++++----- .../components/warm_phase/warm_phase.js | 473 +++++++++--------- .../policy_configuration.js | 13 +- .../policy_selection/policy_selection.js | 63 ++- .../wizard/components/review/diff_view.js | 42 +- .../wizard/components/review/review.js | 219 ++++---- .../sections/wizard/wizard.container.js | 1 + .../public/sections/wizard/wizard.js | 29 +- .../index_management/public/styles/table.less | 2 +- x-pack/yarn.lock | 468 +---------------- yarn.lock | 355 +++---------- 21 files changed, 1094 insertions(+), 1673 deletions(-) create mode 100644 x-pack/plugins/index_lifecycle_management/public/less/main.less diff --git a/package.json b/package.json index 528fea567f10b..2eda9cb138496 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "url": "https://github.com/elastic/kibana.git" }, "dependencies": { - "@elastic/eui": "v0.0.44", + "@elastic/eui": "v0.0.47", "@elastic/filesaver": "1.1.2", "@elastic/numeral": "2.3.2", "@elastic/ui-ace": "0.2.3", diff --git a/x-pack/package.json b/x-pack/package.json index 78b191aca3de9..55ed85b5adbb8 100644 --- a/x-pack/package.json +++ b/x-pack/package.json @@ -75,7 +75,7 @@ "yargs": "4.7.1" }, "dependencies": { - "@elastic/eui": "0.0.44", + "@elastic/eui": "0.0.47", "@elastic/node-crypto": "0.1.2", "@elastic/node-phantom-simple": "2.2.4", "@elastic/numeral": "2.3.2", diff --git a/x-pack/plugins/index_lifecycle_management/public/less/main.less b/x-pack/plugins/index_lifecycle_management/public/less/main.less new file mode 100644 index 0000000000000..392512d93d0c3 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/less/main.less @@ -0,0 +1,49 @@ +@import (reference) "~ui/styles/variables"; + +#indexLifecycleManagementReactRoot { + background: @globalColorLightestGray; + min-height: 100vh; +} + +.euiPageContent.ilmContent { + max-width: 1000px; + width: 100%; +} + +.ilmHrule { + // Less has a bug with calcs + width: calc(~"100% + 48px") !important; + margin-left: -24px; + margin-right: -24px; +} + +.ilmAlias { + display: inline-block; + background-color: #333; + color: white; + padding: 4px 8px; +} + +.ilmDiff__nav { + padding: 16px; + background: #f5f5f5; +} + +.ilmDiff__code { + +} + +.euiAnimateContentLoad { + animation: euiAnimContentLoad $euiAnimSpeedExtraSlow $euiAnimSlightResistance; +} + +@keyframes euiAnimContentLoad { + 0% { + opacity: 0; + transform: translateY(16px); + } + 100% { + opacity: 1; + transform: translateY(0); + } +} diff --git a/x-pack/plugins/index_lifecycle_management/public/main.html b/x-pack/plugins/index_lifecycle_management/public/main.html index 1d1d0036e7fc1..36820f8e159ac 100644 --- a/x-pack/plugins/index_lifecycle_management/public/main.html +++ b/x-pack/plugins/index_lifecycle_management/public/main.html @@ -1,3 +1,3 @@ -
+
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 index 922e593529283..99a5899dd5efe 100644 --- 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 @@ -4,21 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, Component } from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { EuiFlexGroup, EuiFlexItem, - EuiTitle, EuiSpacer, EuiSelect, EuiFieldNumber, - EuiHorizontalRule, EuiCallOut, EuiButtonEmpty, - EuiIconTip, EuiLink, + EuiDescribedFormGroup, } from '@elastic/eui'; import { STRUCTURE_NODE_ATTRS, @@ -93,97 +91,95 @@ export class Configuration extends Component { return (
- - -

Configure options

-
- - - Where do you want your hot indices to live -   - - - } - errorKey={STRUCTURE_NODE_ATTRS} - isShowingErrors={isShowingErrors} - errors={errors} - helpText={selectedNodeAttrs ? ( - - this.setState({ isShowingNodeDetailsFlyout: true }) - } - > - View node details - - ) : null} + Configuration} + titleSize="s" + description="Indices are thought of as "hot" when they are actively being written to." + fullWidth > - { - 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.{' '} - - Learn more. - -

-
- - - - - { - await setSelectedPrimaryShardCount(e.target.value); - validate(); - }} - value={selectedPrimaryShardCount} - /> - - - - - { - await setSelectedReplicaCount(e.target.value); - validate(); - }} - value={selectedReplicaCount} - /> - - - - {this.state.isShowingNodeDetailsFlyout ? ( - this.setState({ isShowingNodeDetailsFlyout: false })} + + 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.{' '} + + Learn more in our docs + . +

+ } /> - ) : null} + + + + + { + await setSelectedPrimaryShardCount(e.target.value); + validate(); + }} + value={selectedPrimaryShardCount} + /> + + + + + { + await setSelectedReplicaCount(e.target.value); + validate(); + }} + value={selectedReplicaCount} + /> + + + + {this.state.isShowingNodeDetailsFlyout ? ( + this.setState({ isShowingNodeDetailsFlyout: false })} + /> + ) : null} - {primaryNodeErrors} + {primaryNodeErrors} +
); } 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 index a158b406762d5..3d5777711a555 100644 --- 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 @@ -7,7 +7,15 @@ import React, { Fragment, PureComponent } from 'react'; import PropTypes from 'prop-types'; -import { EuiSelect, EuiFormRow, EuiSwitch, EuiFieldText } from '@elastic/eui'; +import { + EuiSelect, + EuiFormRow, + EuiSwitch, + EuiFieldText, + EuiDescribedFormGroup, + EuiLink, +} from '@elastic/eui'; + import { ErrableFormRow } from '../../../../form_errors'; import { STRUCTURE_TEMPLATE_NAME, @@ -50,9 +58,22 @@ export class TemplateSelection extends PureComponent { } = this.props; return ( - + Select a template} + fullWidth + titleSize="s" + description={ +

+ An index template defines the settings, mappings, and aliases to apply + when you create an index.{' '} + + Learn more + . +

+ } + > ) : null} -
+ ); } } 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 index b80cbaf77d919..87b620531bf44 100644 --- 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, Component } from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { toastNotifications } from 'ui/notify'; @@ -12,12 +12,8 @@ import { TemplateSelection } from './components/template_selection'; import { Configuration } from './components/configuration'; import { - EuiSpacer, - EuiTitle, EuiHorizontalRule, EuiButton, - EuiTextColor, - EuiLink, } from '@elastic/eui'; import { hasErrors } from '../../../../lib/find_errors'; import { @@ -60,25 +56,6 @@ export class IndexTemplate extends Component { return (
- -

Select a template

-
- - - - -
- An index template defines the settings, mappings, and aliases to apply - when you create an index. -
-
- - - Learn more - -
-
- + - Next + Continue
); 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 index 6bb03853e8f31..7cb2977e706ab 100644 --- 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 @@ -16,6 +16,7 @@ import { EuiSpacer, EuiButtonEmpty, EuiCallOut, + EuiPortal, } from '@elastic/eui'; export class NodeAttrsDetails extends PureComponent { @@ -36,42 +37,44 @@ export class NodeAttrsDetails extends PureComponent { 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 - - -
+ + + + +

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.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/cold_phase/cold_phase.js index 8de43b1f2b4da..13f73ce68b5a7 100644 --- 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 @@ -4,23 +4,22 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { PureComponent } from 'react'; +import React, { PureComponent, Fragment } from 'react'; import PropTypes from 'prop-types'; import { EuiFlexGroup, EuiFlexItem, - EuiIcon, - EuiTitle, EuiSpacer, EuiText, EuiTextColor, - EuiAccordion, EuiFormRow, EuiFieldNumber, EuiSelect, - EuiSwitch, EuiButtonEmpty, + EuiDescribedFormGroup, + EuiBetaBadge, + EuiButton, } from '@elastic/eui'; import { PHASE_ENABLED, @@ -78,153 +77,155 @@ export class ColdPhase extends PureComponent { } = this.props; return ( - - -
- -
-
- - -

Cold phase

-
- + + Cold phase{' '} + {phaseData[PHASE_ENABLED] ? ( + + ) : null} +
+ } + titleSize="s" + description={ + +

+ Your read-only index is queried less frequently. Use this phase + when the index no longer needs to be on the most performant hardware. +

+ {isShowingErrors ? ( + -

- This phase is optional. Your read-only index is queried less frequently. - Use this phase when the index no longer needs to be on the most performant hardware. -

+

This phase contains errors that need to be fixed.

- {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" - /> + ) : null} +
} + fullWidth > -
- -

Configuration

-
- - - - + +
+ + { + await setPhaseData(PHASE_ENABLED, false); + validate(); + }} > - { - 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' } - ]} - /> - - - + Deactive cold phase + +
- + + + + + { + 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' } + ]} + /> + + + - 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(); - }} - /> - - - - + - setPhaseData(PHASE_REPLICA_COUNT, warmPhaseReplicaCount) - } + iconType="eye" + onClick={() => showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])} > - Use number in warm phase + 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(); + }} + /> + + + + + + setPhaseData(PHASE_REPLICA_COUNT, warmPhaseReplicaCount) + } + > + Set 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/delete_phase/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/delete_phase/delete_phase.js index ed28165c9ccc5..7a8a00301023e 100644 --- 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 @@ -7,22 +7,22 @@ -import React, { PureComponent } from 'react'; +import React, { PureComponent, Fragment } from 'react'; import PropTypes from 'prop-types'; import { EuiFlexGroup, EuiFlexItem, - EuiIcon, EuiTitle, EuiSpacer, EuiText, EuiTextColor, - EuiAccordion, EuiFormRow, EuiFieldNumber, EuiSelect, - EuiSwitch, + EuiDescribedFormGroup, + EuiBetaBadge, + EuiButton, } from '@elastic/eui'; import { PHASE_ENABLED, @@ -60,95 +60,100 @@ export class DeletePhase extends PureComponent { } = this.props; return ( - - -
- -
-
- - -

Delete phase

-
- + + Delete phase{' '} + {phaseData[PHASE_ENABLED] ? ( + + ) : null} +
+ } + titleSize="s" + description={ + +

+ When your data is no longer useful. Define how long you want to retain it. +

+ {isShowingErrors ? ( + -

- This phase is optional. Your data is no longer useful. Define how long you want to retain it. -

+

This phase contains errors that need to be fixed.

- {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" - /> + ) : null} + } + fullWidth > -
- -

Configuration

-
- - - - + +
+ + { + await setPhaseData(PHASE_ENABLED, false); + validate(); + }} > - { - 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' } - ]} - /> - - - -
- + Deactive cold 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_ENABLED, true); + validate(); + }} + > + Activate delete phase + +
+ )} + ); } } 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 index ca35b917b0e7c..9511cdac48294 100644 --- 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 @@ -10,16 +10,16 @@ import PropTypes from 'prop-types'; import { EuiFlexGroup, EuiFlexItem, - EuiIcon, - EuiTitle, EuiSpacer, EuiText, EuiTextColor, - EuiAccordion, EuiFieldNumber, EuiSelect, EuiSwitch, - EuiLink + EuiLink, + EuiFormRow, + EuiDescribedFormGroup, + EuiBetaBadge, } from '@elastic/eui'; import { PHASE_ROLLOVER_ALIAS, @@ -66,52 +66,41 @@ export class HotPhase extends PureComponent { } = this.props; return ( - - -
- -
-
- - -

Hot phase

-
- + + Hot phase{' '} + + + } + titleSize="s" + description={ + +

+ This phase is required. Your index is being queried and in active writing mode. +

+ {isShowingErrors ? ( + -

This phase is required. Your index is being queried and in active writing mode.

+

This phase contains errors that need to be fixed.

- {isShowingErrors ? ( - - -

This phase contains errors that need to be fixed.

-
-
- ) : null} -
- + ) : null} + } - buttonClassName="ilmAccordion__button" - buttonContentClassName="ilmAccordion__buttonContent" + fullWidth > -
- -

Rollover condition

-
- + + Setting this to true will rollover the index when it gets too big or too old. The alias will switch to the new index.{' '} + + Learn more. + +

+ } + > { @@ -120,111 +109,99 @@ export class HotPhase extends PureComponent { }} label="Enable rollover" /> - - -

- - Rollover the index when it gets too big or too old. The alias will switch to the new index. - -   - - Learn more. - -

-
- {phaseData[PHASE_ROLLOVER_ENABLED] ? ( - - - - - - { - 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} -
-
+ + {phaseData[PHASE_ROLLOVER_ENABLED] ? ( + + + + + + { + 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/warm_phase/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/components/warm_phase/warm_phase.js index a2a27fd52c639..c627b96bd2a0a 100644 --- 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 @@ -10,18 +10,19 @@ import PropTypes from 'prop-types'; import { EuiFlexGroup, EuiFlexItem, - EuiIcon, EuiTitle, EuiSpacer, EuiText, EuiTextColor, - EuiAccordion, EuiFormRow, EuiFieldNumber, EuiSelect, EuiSwitch, EuiButtonEmpty, EuiLink, + EuiDescribedFormGroup, + EuiBetaBadge, + EuiButton, } from '@elastic/eui'; import { PHASE_ENABLED, @@ -110,227 +111,145 @@ export class WarmPhase extends Component { } = this.props; return ( - - -
- -
-
- - -

Warm phase

-
- + + Warm phase{' '} + {phaseData[PHASE_ENABLED] ? ( + + ) : null} + + } + titleSize="s" + description={ + +

+ Your index is frequently queried, but is read-only. + Use this phase to optimize for search.Your index is being queried + and in active writing mode. +

+ {isShowingErrors ? ( + -

- This phase is optional. Your index is frequently queried, - but is read-only. Use this phase to optimize for search. -

+

This phase contains errors that need to be fixed.

- {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" - /> + ) : null} + } + fullWidth > -
- -

Configuration

-
- - {hotPhaseRolloverEnabled ? ( - - - { - await this.setState({ applyOnRollover: e.target.checked }); - validate(); - }} - /> - - - ) : null} - {!this.state.applyOnRollover ? ( - - - - { - setPhaseData(PHASE_ROLLOVER_AFTER, e.target.value); + + + + {phaseData[PHASE_ENABLED] ? ( + + +
+ { + await setPhaseData(PHASE_ENABLED, false); validate(); }} - /> - - - - - + Remove warm phase + +
+
+ {hotPhaseRolloverEnabled ? ( + + { - await setPhaseData( - PHASE_ROLLOVER_AFTER_UNITS, - e.target.value - ); + await this.setState({ applyOnRollover: e.target.checked }); validate(); }} - options={[ - { value: 'd', text: 'days' }, - { value: 'h', text: 'hours' }, - ]} /> -
-
- ) : null} - - + ) : 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} - - showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS]) - } - > - View node details - - ) : null - } - > - { - await setPhaseData(PHASE_NODE_ATTRS, e.target.value); - validate(); - }} - /> - + - - + showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS]) + } + > + View node details + + ) : null + } > - { - await setPhaseData(PHASE_REPLICA_COUNT, e.target.value); + await setPhaseData(PHASE_NODE_ATTRS, e.target.value); validate(); }} /> - - - - { - await setPhaseData( - PHASE_REPLICA_COUNT, - hotPhaseReplicaCount - ); - validate(); - }} - > - Use number in hot phase - - - - - - - - -

Shrink

-
- - - Shrink the index into a new index with fewer primary shards.{' '} - - Learn more. - - - - - - { - await setPhaseData(PHASE_SHRINK_ENABLED, e.target.checked); - validate(); - }} - label="Enable shrink" - /> - - - - {phaseData[PHASE_SHRINK_ENABLED] ? ( - - + { - await setPhaseData( - PHASE_PRIMARY_SHARD_COUNT, - e.target.value - ); + await setPhaseData(PHASE_REPLICA_COUNT, e.target.value); validate(); }} /> @@ -342,69 +261,151 @@ export class WarmPhase extends Component { flush="left" onClick={async () => { await setPhaseData( - PHASE_PRIMARY_SHARD_COUNT, - hotPhasePrimaryShardCount + PHASE_REPLICA_COUNT, + hotPhaseReplicaCount ); validate(); }} > - Use number in hot phase + Set same as hot phase - - ) : null} - -

Force merge

-
- - - Reduce the number of segments in your shard by and merging smaller - files and clearing deleted ones.{' '} - - Learn More - - - + +

Shrink

+
+ + + Shrink the index into a new index with fewer primary shards.{' '} + + Learn more. + + + + + + + { + await setPhaseData(PHASE_SHRINK_ENABLED, e.target.checked); + validate(); + }} + label="Enable shrink" + /> - + - { - await setPhaseData(PHASE_FORCE_MERGE_ENABLED, e.target.checked); - validate(); - }} - /> + {phaseData[PHASE_SHRINK_ENABLED] ? ( + + + + + { + await setPhaseData( + PHASE_PRIMARY_SHARD_COUNT, + e.target.value + ); + validate(); + }} + /> + + + + + { + await setPhaseData( + PHASE_PRIMARY_SHARD_COUNT, + hotPhasePrimaryShardCount + ); + validate(); + }} + > + Set same as hot phase + + + + + + + + ) : null} + + +

Force merge

+
+ + + Reduce the number of segments in your shard by and merging smaller + files and clearing deleted ones.{' '} + + Learn More + + + - + - {phaseData[PHASE_FORCE_MERGE_ENABLED] ? ( - - { - await setPhaseData( - PHASE_FORCE_MERGE_SEGMENTS, - e.target.value - ); + await setPhaseData(PHASE_FORCE_MERGE_ENABLED, e.target.checked); validate(); }} /> - - ) : null} -
-
+ + + + {phaseData[PHASE_FORCE_MERGE_ENABLED] ? ( + + { + await setPhaseData( + PHASE_FORCE_MERGE_SEGMENTS, + e.target.value + ); + validate(); + }} + /> + + ) : 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/policy_configuration.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/components/policy_configuration/policy_configuration.js index df1c4199ab507..8cabbf599371e 100644 --- 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 @@ -10,6 +10,7 @@ import { toastNotifications } from 'ui/notify'; import { EuiTitle, + EuiText, EuiSpacer, EuiHorizontalRule, EuiButton, @@ -123,14 +124,14 @@ export class PolicyConfiguration extends Component {

- {!selectedPolicyName ? 'Edit new policy' : `Edit policy ${selectedPolicyName}`} + {!selectedPolicyName ? 'Create a new policy' : `Edit policy ${selectedPolicyName}`}

- -
Configure the phases of your data and when to transition between them. Only the hot phase is required.
-
- + +

Configure the phases of your data and when to transition between them. Only the hot phase is required.

+
+ - Next + Continue {this.state.isShowingNodeDetailsFlyout ? ( 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 index 883f7bdadea61..80e10110baa1b 100644 --- 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 @@ -8,14 +8,12 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { - EuiFlexGrid, EuiFlexGroup, EuiFlexItem, - EuiIcon, - EuiTitle, - EuiSpacer, - EuiPanel, - EuiText, + EuiButton, + EuiDescribedFormGroup, + EuiFormRow, + EuiSelect, } from '@elastic/eui'; export class PolicySelection extends Component { @@ -38,25 +36,48 @@ export class PolicySelection extends Component { // this.props.done(); } + render() { const { policies, existingPolicyName } = this.props; + let options = []; + options = policies.map(item => ({ value: item.name, text: item.name })); + + console.log(policies); + return ( -
- - - -

Select a policy

-
- -

- An index lifecycle policy is a blueprint for transitioning your data over time. - You can create a new policy or edit an existing policy and save it with a new name. -

-
+ Select or create a policy} + titleSize="s" + description="An index lifecycle policy is a + blueprint for transitioning your data over time. + You can create a new policy or edit an existing + policy and save it with a new name." + fullWidth + > + + + + { + await this.selectPolicy(e.target.value); + }} + /> + + + + + this.selectPolicy(null)} + > + Create new policy + + - + {/* ))} + */} + {/* */} {/* Back */} -
+ ); } } 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 index 77809dc140e53..7f743e048fd46 100644 --- 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 @@ -4,17 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, PureComponent } from 'react'; +import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { EuiCodeEditor, - EuiDescriptionList, - EuiDescriptionListTitle, - EuiDescriptionListDescription, EuiFlexGroup, EuiFlexItem, EuiButtonEmpty, + EuiToolTip, + EuiCode, } from '@elastic/eui'; import ace from 'brace'; import 'brace/mode/json'; @@ -68,30 +67,31 @@ export class DiffView extends PureComponent { addDiffAddonsForAce(); return ( - - - + + +
    {changes.map(({ key, original, updated }) => ( - - - this.scrollToKey(key, updated)}> - {key} - - - - {original ? ( +
  • + - Changing `{JSON.stringify(original)}` to `{JSON.stringify(updated)}`` + Changing the value of {key} from {JSON.stringify(original)} + to {JSON.stringify(updated)} ) : ( - Adding with `{JSON.stringify(updated)}` + Setting a value of {JSON.stringify(updated)} for {key} )} - - + > + this.scrollToKey(key, updated)}> + {key} + + +
  • ))} - +
- + (this.aceEditor = aceEditor)} mode="diff_json" 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 5c61331258f9f..fff16b7af2bb4 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 @@ -18,18 +18,19 @@ import 'brace/ext/language_tools'; import { EuiTitle, + EuiCode, + EuiCallOut, EuiSpacer, EuiHorizontalRule, EuiButton, EuiFlexItem, - EuiFlexGrid, - EuiPanel, EuiText, EuiButtonEmpty, EuiFormRow, EuiSwitch, EuiFieldText, EuiLoadingSpinner, + EuiFlexGroup, } from '@elastic/eui'; import { getAffectedIndices } from '../../../../api'; import { DiffView } from './diff_view'; @@ -141,99 +142,54 @@ export class Review extends Component { */} + +

Review your policy changes

+
+ +

Be careful. Your changes will go into effect immediately once you save.

+
- - {originalPolicyName ? ( - - { - await setSaveAsNewPolicy(e.target.checked); - validate(); - }} - label={ - - Save this as a new policy so it does not - effect other templates. - - } - /> - - ) : null} - {saveAsNewPolicy ? ( - + + +

{`${affectedIndexTemplates.length} Affected index ${affectedIndexTemplates.length === 1 ? 'template' : 'templates'}`}

+
    + {affectedIndexTemplates.map(template => ( +
  • {template}
  • + ))} +
+

{`${affectedIndices.length} Affected ${affectedIndices.length === 1 ? 'Index' : 'Indices' }`}

+ { isLoadingAffectedIndices ? ( + + ) : ( +
    + {affectedIndices.map(index =>
  • {index}
  • )} +
+ ) } +
+ + {bootstrapEnabled ? ( + + + - { - await setSelectedPolicyName(e.target.value); - validate(); - }} - /> -
- ) : null} -
- - - - - -

{affectedIndexTemplates.length} Affected Index {affectedIndexTemplates.length === 1 ? 'Template' : 'Templates' }

-
- -
    - {affectedIndexTemplates.map(template => ( -
  • {template}
  • - ))} -
-
-
-
- - - -

{affectedIndices.length} Affected {affectedIndices.length === 1 ? 'Index' : 'Indices' }

-
- - { isLoadingAffectedIndices ? ( - - ) : ( -
    - {affectedIndices.map(index =>
  • {index}
  • )} -
- ) } -
-
-
- {bootstrapEnabled ? ( - - - -

New alias

-
- -

Point to this new alias going forward:

-
    -
  • {aliasName}
  • -
-
-
-
- ) : null} -
+

Since you decided to bootstrap a new index you'll want to point to a new alias going forward

+

{aliasName} is your new alias

+ + + ) : null} + {templateDiff.hasChanged ? (

- We will be changing the index template named `{ - selectedIndexTemplateName - }` + {selectedIndexTemplateName} template changes

@@ -258,18 +214,83 @@ export class Review extends Component {
) : null} - - Back - + + + + {originalPolicyName ? ( + + +

Save changes to {originalPolicyName} policy

+
+ +

+ You are editing an existing policy. This means that any saves you make + will also change any index templates this policy is attached to. You can instead save + these changes and make it a brand new policy that only changes the template you + selected. +

+
+ + + { + await setSaveAsNewPolicy(e.target.checked); + validate(); + }} + label={ + + Save this as a new policy + + } + /> + +
+ ) : null} + {saveAsNewPolicy ? ( + + +

Save your work

+
+ + + { + await setSelectedPolicyName(e.target.value); + validate(); + }} + /> + +
+ ) : null} +
+ + + + + Back + + + + + done(lifecycle)} + > + Looks good, save changes + + +    - done(lifecycle)} - > - Looks good, save changes - ); } 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 index 57eb484bcc0fd..2b76624165a78 100644 --- 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 @@ -8,6 +8,7 @@ import { connect } from 'react-redux'; +import '../../less/main.less'; import { Wizard as PresentationComponent } from './wizard'; import { saveLifecycle } from '../../store/actions'; import { 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 index 63d6a7c00a83e..3a7ba64893b23 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js @@ -13,8 +13,8 @@ import { PolicyConfiguration } from './components/policy_configuration'; import { Review } from './components/review'; import { EuiPage, - EuiFlexGroup, - EuiFlexItem, + EuiPageBody, + EuiPageContent, EuiTitle, EuiSpacer, EuiStepsHorizontal, @@ -163,20 +163,21 @@ export class Wizard extends Component { return ( - - - + + +

Index lifecycle management

-
-
- - - - {/* */} - {this.renderContent()} + + + + + {/* */} + {this.renderContent()} + +
); } diff --git a/x-pack/plugins/index_management/public/styles/table.less b/x-pack/plugins/index_management/public/styles/table.less index bd2b7a65c443e..2f365744e8da0 100644 --- a/x-pack/plugins/index_management/public/styles/table.less +++ b/x-pack/plugins/index_management/public/styles/table.less @@ -8,7 +8,7 @@ .indexTableHorizontalScrollContainer { overflow-x: auto; max-width: 100%; - height: 100vh; + min-height: 100vh; } .indexTableHorizontalScroll { min-width: 800px; diff --git a/x-pack/yarn.lock b/x-pack/yarn.lock index 1f44d67006d6e..3da71d5ea98f8 100644 --- a/x-pack/yarn.lock +++ b/x-pack/yarn.lock @@ -10,30 +10,25 @@ esutils "^2.0.2" js-tokens "^3.0.0" -"@elastic/eui@0.0.44": - version "0.0.44" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.44.tgz#b0b58eb1b10d6f8de017f548bb06c5b5f71e3d61" +"@elastic/eui@0.0.47": + version "0.0.47" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.47.tgz#5bae27966bb1d68bb3106853610a407509053b44" dependencies: brace "^0.10.0" classnames "^2.2.5" core-js "^2.5.1" - eslint-config-prettier "^2.9.0" - eslint-plugin-prettier "^2.6.0" focus-trap-react "^3.0.4" highlight.js "^9.12.0" html "^1.0.0" - jquery "^3.2.1" keymirror "^0.1.1" lodash "^3.10.1" numeral "^2.0.6" - prettier "^1.11.1" prop-types "^15.6.0" react-ace "^5.5.0" react-color "^2.13.8" react-datepicker v1.4.1 react-input-autosize "^2.2.1" react-virtualized "^9.18.5" - serve "^6.3.1" tabbable "^1.1.0" uuid "^3.1.0" @@ -97,13 +92,6 @@ accept@2.x.x: boom "5.x.x" hoek "4.x.x" -accepts@~1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" - dependencies: - mime-types "~2.1.18" - negotiator "0.6.1" - acorn-globals@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.1.0.tgz#ab716025dbe17c54d3ef81d32ece2b2d99fe2538" @@ -122,10 +110,6 @@ add-event-listener@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/add-event-listener/-/add-event-listener-0.0.1.tgz#a76229ebc64c8aefae204a16273a2f255abea2d0" -address@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" - agentkeepalive@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-2.2.0.tgz#c5d1bd4b129008f1163f236f86e5faea2026e2ef" @@ -185,12 +169,6 @@ angular-ui-bootstrap@1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/angular-ui-bootstrap/-/angular-ui-bootstrap-1.2.5.tgz#b0c1eff0bf3b7a65668984a1b81820a90dc60995" -ansi-align@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" - dependencies: - string-width "^2.0.0" - ansi-cyan@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" @@ -276,10 +254,6 @@ aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" -arch@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.0.tgz#3613aa46149064b3c1f0607919bf1d4786e82889" - archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" @@ -304,15 +278,6 @@ argparse@~0.1.15: underscore "~1.7.0" underscore.string "~2.4.0" -args@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/args/-/args-4.0.0.tgz#5ca24cdba43d4b17111c56616f5f2e9d91933954" - dependencies: - camelcase "5.0.0" - chalk "2.3.2" - leven "2.1.0" - mri "1.1.0" - argv-split@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/argv-split/-/argv-split-2.0.1.tgz#be264117790dbd5ccd63ec3f449a1804814ac4c5" @@ -947,12 +912,6 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" -basic-auth@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.0.tgz#015db3f353e02e56377755f962742e8981e7bbba" - dependencies: - safe-buffer "5.1.1" - bcrypt-pbkdf@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" @@ -979,7 +938,7 @@ bluebird@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.1.1.tgz#7e2e4318d62ae72a674f6aea6357bb4def1a6e41" -bluebird@3.5.1, bluebird@^3.3.1: +bluebird@^3.3.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -1017,18 +976,6 @@ boom@5.x.x: dependencies: hoek "4.x.x" -boxen@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" - dependencies: - ansi-align "^2.0.0" - camelcase "^4.0.0" - chalk "^2.0.1" - cli-boxes "^1.0.0" - string-width "^2.0.0" - term-size "^1.2.0" - widest-line "^2.0.0" - brace-expansion@^1.0.0, brace-expansion@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" @@ -1144,10 +1091,6 @@ builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" -bytes@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" @@ -1180,10 +1123,6 @@ camelcase-keys@^2.0.0: camelcase "^2.0.0" map-obj "^1.0.0" -camelcase@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" - camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" @@ -1196,7 +1135,7 @@ camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" -camelcase@^4.0.0, camelcase@^4.1.0: +camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -1232,22 +1171,6 @@ chai@~1.9.2: assertion-error "1.0.0" deep-eql "0.1.3" -chalk@2.3.2, chalk@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.0.tgz#a060a297a6b57e15b61ca63ce84995daa0fe6e52" - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - chalk@^1.0.0, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -1266,6 +1189,14 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" +chalk@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chance@1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/chance/-/chance-1.0.10.tgz#03500b04ad94e778dd2891b09ec73a6ad87b1996" @@ -1312,10 +1243,6 @@ classnames@2.2.5, classnames@^2.1.2, classnames@^2.2.3, classnames@^2.2.4, class version "2.2.5" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" -cli-boxes@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" - cli-cursor@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" @@ -1334,13 +1261,6 @@ clipboard@^1.6.1: select "^1.1.2" tiny-emitter "^2.0.0" -clipboardy@1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.3.tgz#0526361bf78724c1f20be248d428e365433c07ef" - dependencies: - arch "^2.1.0" - execa "^0.8.0" - cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" @@ -1460,24 +1380,6 @@ component-emitter@^1.2.0, component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" -compressible@~2.0.13: - version "2.0.13" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.13.tgz#0d1020ab924b2fdb4d6279875c7d6daba6baa7a9" - dependencies: - mime-db ">= 1.33.0 < 2" - -compression@^1.6.2: - version "1.7.2" - resolved "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz#aaffbcd6aaf854b44ebb280353d5ad1651f59a69" - dependencies: - accepts "~1.3.4" - bytes "3.0.0" - compressible "~2.0.13" - debug "2.6.9" - on-headers "~1.0.1" - safe-buffer "5.1.1" - vary "~1.1.2" - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1514,10 +1416,6 @@ content-type-parser@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.2.tgz#caabe80623e63638b2502fd4c7f12ff4ce2352e7" -content-type@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - content@3.x.x: version "3.0.6" resolved "https://registry.yarnpkg.com/content/-/content-3.0.6.tgz#9c2e301e9ae515ed65a4b877d78aa5659bb1b809" @@ -1789,10 +1687,6 @@ d3@3.5.6: version "3.5.6" resolved "https://registry.yarnpkg.com/d3/-/d3-3.5.6.tgz#9451c651ca733fb9672c81fb7f2655164a73a42d" -dargs@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/dargs/-/dargs-5.1.0.tgz#ec7ea50c78564cd36c9d5ec18f66329fade27829" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -1828,7 +1722,7 @@ debug@2.2.0: dependencies: ms "0.7.1" -debug@2.6.9, debug@2.X, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8: +debug@2.X, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: @@ -1937,22 +1831,10 @@ delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" -depd@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359" - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - deprecated@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19" -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - detect-file@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" @@ -1971,13 +1853,6 @@ detect-newline@2.X, detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" -detect-port@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.2.2.tgz#57a44533632d8bc74ad255676866ca43f96c7469" - dependencies: - address "^1.0.1" - debug "^2.6.0" - dfa@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/dfa/-/dfa-1.1.0.tgz#d30218bd10d030fa421df3ebbc82285463a31781" @@ -2093,10 +1968,6 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - elasticsearch@13.0.1: version "13.0.1" resolved "https://registry.yarnpkg.com/elasticsearch/-/elasticsearch-13.0.1.tgz#fa58204233052c4cd221e8721e48f3906b385b32" @@ -2108,10 +1979,6 @@ elasticsearch@13.0.1: lodash.isempty "^4.4.0" lodash.trimend "^4.5.1" -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - encoding@^0.1.11: version "0.1.12" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" @@ -2204,10 +2071,6 @@ es6-promise@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-2.0.1.tgz#ccc4963e679f0ca9fb187c777b9e583d3c7573c2" -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - escape-string-regexp@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" @@ -2256,19 +2119,6 @@ escodegen@~1.3.2: optionalDependencies: source-map "~0.1.33" -eslint-config-prettier@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-2.9.0.tgz#5ecd65174d486c22dff389fe036febf502d468a3" - dependencies: - get-stdin "^5.0.1" - -eslint-plugin-prettier@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz#33e4e228bdb06142d03c560ce04ec23f6c767dd7" - dependencies: - fast-diff "^1.1.1" - jest-docblock "^21.0.0" - esprima@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" @@ -2305,10 +2155,6 @@ esutils@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - exec-sh@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.2.1.tgz#163b98a6e89e6b65b47c2a28d215bc1f63989c38" @@ -2339,18 +2185,6 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - exit-hook@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" @@ -2492,10 +2326,6 @@ fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" -fast-diff@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" - fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -2554,10 +2384,6 @@ fileset@^2.0.2: glob "^7.0.3" minimatch "^3.0.3" -filesize@3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" - fill-keys@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/fill-keys/-/fill-keys-1.0.2.tgz#9a8fa36f4e8ad634e3bf6b4f3c8882551452eb20" @@ -2735,22 +2561,10 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - from@^0.1.3: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" -fs-extra@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-mkdirp-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" @@ -2837,10 +2651,6 @@ get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" -get-stdin@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" - get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -3240,7 +3050,7 @@ gulplog@^1.0.0: dependencies: glogg "^1.0.0" -handlebars@4.0.11, handlebars@^4.0.3: +handlebars@^4.0.3: version "4.0.11" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" dependencies: @@ -3479,15 +3289,6 @@ htmlparser2@^3.9.1: inherits "^2.0.1" readable-stream "^2.0.2" -http-errors@1.6.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736" - dependencies: - depd "1.1.1" - inherits "2.0.3" - setprototypeof "1.0.3" - statuses ">= 1.3.1 < 2" - http-errors@~1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.4.0.tgz#6c0242dea6b3df7afda153c71089b31c6e82aabf" @@ -3495,15 +3296,6 @@ http-errors@~1.4.0: inherits "2.0.1" statuses ">= 1.2.1 < 2" -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - http-signature@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" @@ -3570,7 +3362,7 @@ inherits@1: version "1.0.2" resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b" -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -3615,10 +3407,6 @@ invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" -ip@1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - iron@4.x.x: version "4.0.5" resolved "https://registry.yarnpkg.com/iron/-/iron-4.0.5.tgz#4f042cceb8b9738f346b59aa734c83a89bc31428" @@ -3838,7 +3626,7 @@ is-relative@^1.0.0: dependencies: is-unc-path "^1.0.0" -is-stream@1.1.0, is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -3876,10 +3664,6 @@ is-windows@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.1.tgz#310db70f742d259a16a369202b51af84233310d9" -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -4069,10 +3853,6 @@ jest-diff@^22.4.3: jest-get-type "^22.4.3" pretty-format "^22.4.3" -jest-docblock@^21.0.0: - version "21.2.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414" - jest-docblock@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-22.4.3.tgz#50886f132b42b280c903c592373bb6e93bb68b19" @@ -4309,7 +4089,7 @@ jquery@^3.1.1: version "3.2.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.2.1.tgz#5c4d9de652af6cd0a770154a631bba12b015c787" -jquery@^3.2.1, jquery@^3.3.1: +jquery@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" @@ -4387,12 +4167,6 @@ json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - optionalDependencies: - graceful-fs "^4.1.6" - jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -4480,7 +4254,7 @@ left-pad@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.2.0.tgz#d30a73c6b8201d8f7d8e7956ba9616087a68e0ee" -leven@2.1.0, leven@^2.1.0: +leven@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" @@ -4862,21 +4636,6 @@ methods@^1.1.1, methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" -micro-compress@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micro-compress/-/micro-compress-1.0.0.tgz#53f5a80b4ad0320ca165a559b6e3df145d4f704f" - dependencies: - compression "^1.6.2" - -micro@9.1.4: - version "9.1.4" - resolved "https://registry.yarnpkg.com/micro/-/micro-9.1.4.tgz#dbe655f34bb3390509898ddf3fda12348f5cbaa9" - dependencies: - content-type "1.0.4" - is-stream "1.1.0" - mri "1.1.0" - raw-body "2.3.2" - micromatch@^2.1.5, micromatch@^2.3.11, micromatch@^2.3.7: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" @@ -4917,30 +4676,16 @@ mime-db@1.x.x: version "1.32.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.32.0.tgz#485b3848b01a3cda5f968b4882c0771e58e09414" -"mime-db@>= 1.33.0 < 2", mime-db@~1.33.0: - version "1.33.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" - mime-db@~1.30.0: version "1.30.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" -mime-types@2.1.18, mime-types@~2.1.18: - version "2.1.18" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" - dependencies: - mime-db "~1.33.0" - mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7: version "2.1.17" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" dependencies: mime-db "~1.30.0" -mime@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - mime@^1.4.1: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -5071,10 +4816,6 @@ moment@2.x.x, "moment@>= 2.9.0", moment@^2.13.0, moment@^2.20.1: version "2.20.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.20.1.tgz#d6eb1a46cbcc14a2b2f9434112c1ff8907f313fd" -mri@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.0.tgz#5c0a3f29c8ccffbbb1ec941dcec09d71fa32f36a" - ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" @@ -5145,10 +4886,6 @@ nearley@^2.7.10: railroad-diagrams "^1.0.0" randexp "^0.4.2" -negotiator@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" - ngreact@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/ngreact/-/ngreact-0.5.1.tgz#2dcccc1541771796689d13e51bb8d5010af41c57" @@ -5204,10 +4941,6 @@ node-pre-gyp@^0.6.39: tar "^2.2.1" tar-pack "^3.4.0" -node-version@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.1.3.tgz#1081c87cce6d2dbbd61d0e51e28c287782678496" - nomnom@~1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.6.2.tgz#84a66a260174408fc5b77a18f888eccc44fb6971" @@ -5389,16 +5122,6 @@ object.values@^1.0.4: function-bind "^1.1.0" has "^1.0.1" -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - dependencies: - ee-first "1.1.1" - -on-headers@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" - once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.3.3, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -5415,16 +5138,6 @@ onetime@^1.0.0: version "1.1.0" resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" -openssl-self-signed-certificate@1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/openssl-self-signed-certificate/-/openssl-self-signed-certificate-1.1.6.tgz#9d3a4776b1a57e9847350392114ad2f915a83dd4" - -opn@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.3.0.tgz#64871565c863875f052cfdf53d3e3cb5adb53b1c" - dependencies: - is-wsl "^1.1.0" - optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -5586,7 +5299,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-is-inside@1.0.2, path-is-inside@^1.0.1: +path-is-inside@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" @@ -5621,12 +5334,6 @@ path-to-regexp@^1.0.0, path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" -path-type@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - dependencies: - pify "^3.0.0" - path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -5689,10 +5396,6 @@ pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" @@ -5797,10 +5500,6 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -prettier@^1.11.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325" - pretty-format@^22.4.3: version "22.4.3" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-22.4.3.tgz#f873d780839a9c02e9664c8a082e9ee79eaac16f" @@ -5973,28 +5672,6 @@ randomatic@^1.1.3: is-number "^3.0.0" kind-of "^4.0.0" -range-parser@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - -raw-body@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.2.tgz#bcd60c77d3eb93cde0050295c3f379389bc88f89" - dependencies: - bytes "3.0.0" - http-errors "1.6.2" - iconv-lite "0.4.19" - unpipe "1.0.0" - -rc@^1.0.1, rc@^1.1.6: - version "1.2.6" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.6.tgz#eb18989c6d4f4f162c399f79ddd29f3835568092" - dependencies: - deep-extend "~0.4.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - rc@^1.1.7: version "1.2.3" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.3.tgz#51575a900f8dd68381c710b4712c2154c3e2035b" @@ -6390,19 +6067,6 @@ regexpu-core@^2.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -registry-auth-token@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" - dependencies: - rc "^1.1.6" - safe-buffer "^5.0.1" - -registry-url@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" - dependencies: - rc "^1.0.1" - regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" @@ -6685,7 +6349,7 @@ rxjs@5.3.0: dependencies: symbol-observable "^1.0.1" -safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -6747,55 +6411,10 @@ semver@^5.4.1, semver@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" -send@0.16.2: - version "0.16.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.4.0" - sequencify@~0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c" -serve@^6.3.1: - version "6.5.6" - resolved "https://registry.yarnpkg.com/serve/-/serve-6.5.6.tgz#579136688f80f6bf4a618ca8e8cba10dfb4d95e3" - dependencies: - args "4.0.0" - basic-auth "2.0.0" - bluebird "3.5.1" - boxen "1.3.0" - chalk "2.4.0" - clipboardy "1.2.3" - dargs "5.1.0" - detect-port "1.2.2" - filesize "3.6.1" - fs-extra "5.0.0" - handlebars "4.0.11" - ip "1.1.5" - micro "9.1.4" - micro-compress "1.0.0" - mime-types "2.1.18" - node-version "1.1.3" - openssl-self-signed-certificate "1.1.6" - opn "5.3.0" - path-is-inside "1.0.2" - path-type "3.0.0" - send "0.16.2" - update-check "1.3.2" - set-blocking@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-1.0.0.tgz#cd5e5d938048df1ac92dfe92e1f16add656f5ec5" @@ -6832,14 +6451,6 @@ setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" -setprototypeof@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" - -setprototypeof@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" - shallow-copy@~0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170" @@ -7088,14 +6699,10 @@ static-module@^1.1.0: static-eval "~0.2.0" through2 "~0.4.1" -"statuses@>= 1.2.1 < 2", statuses@~1.4.0: +"statuses@>= 1.2.1 < 2": version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" -"statuses@>= 1.3.1 < 2", "statuses@>= 1.4.0 < 2": - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" @@ -7353,12 +6960,6 @@ temp@^0.8.3: os-tmpdir "^1.0.0" rimraf "~2.2.6" -term-size@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" - dependencies: - execa "^0.7.0" - test-exclude@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" @@ -7662,14 +7263,6 @@ unique-stream@^2.0.2: json-stable-stringify "^1.0.0" through2-filter "^2.0.0" -universalify@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" - -unpipe@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -7677,13 +7270,6 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" -update-check@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/update-check/-/update-check-1.3.2.tgz#460f9e9ab24820367f3edbeb4d4142d9936ff171" - dependencies: - registry-auth-token "3.3.2" - registry-url "3.1.0" - urix@^0.1.0, urix@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" @@ -7746,10 +7332,6 @@ value-or-function@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - venn.js@0.2.9: version "0.2.9" resolved "https://registry.yarnpkg.com/venn.js/-/venn.js-0.2.9.tgz#33c29075efa484731d59d884752900cc33033656" @@ -7948,12 +7530,6 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2" -widest-line@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.0.tgz#0142a4e8a243f8882c0233aa0e0281aa76152273" - dependencies: - string-width "^2.1.1" - window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" diff --git a/yarn.lock b/yarn.lock index cdda60551b8cc..8f573bc2f01fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -77,30 +77,25 @@ version "0.0.0" uid "" -"@elastic/eui@0.0.44", "@elastic/eui@v0.0.44": - version "0.0.44" - resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.44.tgz#b0b58eb1b10d6f8de017f548bb06c5b5f71e3d61" +"@elastic/eui@0.0.47", "@elastic/eui@v0.0.47": + version "0.0.47" + resolved "https://registry.yarnpkg.com/@elastic/eui/-/eui-0.0.47.tgz#5bae27966bb1d68bb3106853610a407509053b44" dependencies: brace "^0.10.0" classnames "^2.2.5" core-js "^2.5.1" - eslint-config-prettier "^2.9.0" - eslint-plugin-prettier "^2.6.0" focus-trap-react "^3.0.4" highlight.js "^9.12.0" html "^1.0.0" - jquery "^3.2.1" keymirror "^0.1.1" lodash "^3.10.1" numeral "^2.0.6" - prettier "^1.11.1" prop-types "^15.6.0" react-ace "^5.5.0" react-color "^2.13.8" react-datepicker v1.4.1 react-input-autosize "^2.2.1" react-virtualized "^9.18.5" - serve "^6.3.1" tabbable "^1.1.0" uuid "^3.1.0" @@ -181,14 +176,6 @@ version "9.4.7" resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.7.tgz#57d81cd98719df2c9de118f2d5f3b1120dcd7275" -"@zeit/check-updates@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@zeit/check-updates/-/check-updates-1.1.0.tgz#d0f65026a36f27cd1fd54c647d8294447c1d2d8b" - dependencies: - chalk "2.3.0" - ms "2.1.1" - update-notifier "2.3.0" - JSONStream@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.1.1.tgz#c98bfd88c8f1e1e8694e53c5baa6c8691553e59a" @@ -226,13 +213,6 @@ accepts@1.3.3: mime-types "~2.1.11" negotiator "0.6.1" -accepts@~1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.5.tgz#eb777df6011723a3b14e8a72c0805c8e86746bd2" - dependencies: - mime-types "~2.1.18" - negotiator "0.6.1" - acorn-dynamic-import@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4" @@ -281,10 +261,6 @@ add-event-listener@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/add-event-listener/-/add-event-listener-0.0.1.tgz#a76229ebc64c8aefae204a16273a2f255abea2d0" -address@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" - adm-zip@0.4.7: version "0.4.7" resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.4.7.tgz#8606c2cbf1c426ce8c8ec00174447fd49b6eafc1" @@ -513,10 +489,6 @@ aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" -arch@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.0.tgz#3613aa46149064b3c1f0607919bf1d4786e82889" - are-we-there-yet@~1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" @@ -537,16 +509,6 @@ argparse@~0.1.15: underscore "~1.7.0" underscore.string "~2.4.0" -args@3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/args/-/args-3.0.8.tgz#2f425ab639c69d74ff728f3d7c6e93b97b91af7c" - dependencies: - camelcase "4.1.0" - chalk "2.1.0" - mri "1.1.0" - pkginfo "0.4.1" - string-similarity "1.2.0" - arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" @@ -1567,12 +1529,6 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" -basic-auth@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.0.tgz#015db3f353e02e56377755f962742e8981e7bbba" - dependencies: - safe-buffer "5.1.1" - batch-processor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/batch-processor/-/batch-processor-1.0.0.tgz#75c95c32b748e0850d10c2b168f6bdbe9891ace8" @@ -1629,14 +1585,14 @@ bluebird@3.4.6: version "3.4.6" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.6.tgz#01da8d821d87813d158967e743d5fe6c62cf8c0f" -bluebird@3.5.1, bluebird@^3.3.0: - version "3.5.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" - bluebird@^2.10.0, bluebird@^2.9.24: version "2.11.0" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" +bluebird@^3.3.0: + version "3.5.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" + bmp-js@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.0.3.tgz#64113e9c7cf1202b376ed607bf30626ebe57b18a" @@ -1723,7 +1679,7 @@ boom@5.2.0, boom@5.x.x: dependencies: hoek "4.x.x" -boxen@1.3.0, boxen@^1.2.1, boxen@^1.2.2: +boxen@^1.2.1, boxen@^1.2.2: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" dependencies: @@ -2071,10 +2027,6 @@ camelcase-keys@^3.0.0: camelcase "^3.0.0" map-obj "^1.0.0" -camelcase@4.1.0, camelcase@^4.0.0, camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - camelcase@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" @@ -2087,6 +2039,10 @@ camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" +camelcase@^4.0.0, camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + caniuse-api@^1.5.2: version "1.6.1" resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c" @@ -2146,14 +2102,6 @@ chai@3.5.0, "chai@>=1.9.2 <4.0.0": deep-eql "^0.1.3" type-detect "^1.0.0" -chalk@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" - chalk@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" @@ -2162,14 +2110,6 @@ chalk@2.3.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" -chalk@2.3.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3, chalk@~1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -2180,6 +2120,14 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3, chalk@~1.1.1: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1, chalk@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + chalk@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" @@ -2396,13 +2344,6 @@ clipboard@^1.6.1: select "^1.1.2" tiny-emitter "^2.0.0" -clipboardy@1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.3.tgz#0526361bf78724c1f20be248d428e365433c07ef" - dependencies: - arch "^2.1.0" - execa "^0.8.0" - cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" @@ -2614,24 +2555,6 @@ component-inherit@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" -compressible@~2.0.13: - version "2.0.13" - resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.13.tgz#0d1020ab924b2fdb4d6279875c7d6daba6baa7a9" - dependencies: - mime-db ">= 1.33.0 < 2" - -compression@^1.6.2: - version "1.7.2" - resolved "http://registry.npmjs.org/compression/-/compression-1.7.2.tgz#aaffbcd6aaf854b44ebb280353d5ad1651f59a69" - dependencies: - accepts "~1.3.4" - bytes "3.0.0" - compressible "~2.0.13" - debug "2.6.9" - on-headers "~1.0.1" - safe-buffer "5.1.1" - vary "~1.1.2" - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -2746,7 +2669,7 @@ content-type-parser@^1.0.1, content-type-parser@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.2.tgz#caabe80623e63638b2502fd4c7f12ff4ce2352e7" -content-type@1.0.4, content-type@~1.0.1, content-type@~1.0.4: +content-type@~1.0.1, content-type@~1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" @@ -3308,10 +3231,6 @@ d@1: dependencies: es5-ext "^0.10.9" -dargs@5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/dargs/-/dargs-5.1.0.tgz#ec7ea50c78564cd36c9d5ec18f66329fade27829" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -3341,7 +3260,7 @@ debug@0.7.4: version "0.7.4" resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" -debug@2, debug@2.6.9, debug@2.X, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9: +debug@2, debug@2.6.9, debug@2.X, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.6, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: @@ -3538,7 +3457,7 @@ depd@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/depd/-/depd-1.0.1.tgz#80aec64c9d6d97e65cc2a9caa93c0aa6abf73aaa" -depd@~1.1.0, depd@~1.1.1, depd@~1.1.2: +depd@~1.1.0, depd@~1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" @@ -3549,10 +3468,6 @@ des.js@^1.0.0: inherits "^2.0.1" minimalistic-assert "^1.0.0" -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" @@ -3567,13 +3482,6 @@ detect-newline@2.X, detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" -detect-port@1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.2.2.tgz#57a44533632d8bc74ad255676866ca43f96c7469" - dependencies: - address "^1.0.1" - debug "^2.6.0" - dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -3856,7 +3764,7 @@ encode-uri-query@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/encode-uri-query/-/encode-uri-query-1.0.0.tgz#d632be4aafe8316c6145007ffb2844c5312b194c" -encodeurl@~1.0.1, encodeurl@~1.0.2: +encodeurl@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -4375,10 +4283,6 @@ esutils@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esutils/-/esutils-1.0.0.tgz#8151d358e20c8acc7fb745e7472c0025fe496570" -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - even-better@7.0.2: version "7.0.2" resolved "https://registry.yarnpkg.com/even-better/-/even-better-7.0.2.tgz#d056f429c90ecc20ee9494aca0a751f743504d2e" @@ -4457,18 +4361,6 @@ execa@^0.7.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -execa@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.9.0.tgz#adb7ce62cf985071f60580deb4a88b9e34712d01" @@ -4784,10 +4676,6 @@ fileset@^2.0.2: glob "^7.0.3" minimatch "^3.0.3" -filesize@3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.0.tgz#22d079615624bb6fd3c04026120628a41b3f4efa" - fill-keys@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/fill-keys/-/fill-keys-1.0.2.tgz#9a8fa36f4e8ad634e3bf6b4f3c8882551452eb20" @@ -4982,10 +4870,6 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - from@^0.1.3, from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" @@ -5008,14 +4892,6 @@ fs-extra@4.0.3, fs-extra@^4.0.1: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" @@ -5641,9 +5517,9 @@ h2o2@5.1.1: joi "9.X.X" wreck "9.X.X" -handlebars@4.0.11, handlebars@^4.0.1, handlebars@^4.0.3: - version "4.0.11" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" +handlebars@4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.5.tgz#92c6ed6bb164110c50d4d8d0fbddc70806c6f8e7" dependencies: async "^1.4.0" optimist "^0.6.1" @@ -5651,9 +5527,9 @@ handlebars@4.0.11, handlebars@^4.0.1, handlebars@^4.0.3: optionalDependencies: uglify-js "^2.6" -handlebars@4.0.5: - version "4.0.5" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.5.tgz#92c6ed6bb164110c50d4d8d0fbddc70806c6f8e7" +handlebars@^4.0.1, handlebars@^4.0.3: + version "4.0.11" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.11.tgz#630a35dfe0294bc281edae6ffc5d329fc7982dcc" dependencies: async "^1.4.0" optimist "^0.6.1" @@ -6262,10 +6138,6 @@ ip-regex@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd" -ip@1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - iron@4.x.x: version "4.0.5" resolved "https://registry.yarnpkg.com/iron/-/iron-4.0.5.tgz#4f042cceb8b9738f346b59aa734c83a89bc31428" @@ -6612,7 +6484,7 @@ is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" -is-stream@1.1.0, is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: +is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" @@ -6670,10 +6542,6 @@ is-word-character@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.1.tgz#5a03fa1ea91ace8a6eb0c7cd770eb86d65c8befb" -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -7348,7 +7216,7 @@ jpeg-js@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.2.0.tgz#53e448ec9d263e683266467e9442d2c5a2ef5482" -jquery@^3.1.1, jquery@^3.2.1, jquery@^3.3.1: +jquery@^3.1.1, jquery@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca" @@ -8433,21 +8301,6 @@ methods@^1.1.1, methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" -micro-compress@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/micro-compress/-/micro-compress-1.0.0.tgz#53f5a80b4ad0320ca165a559b6e3df145d4f704f" - dependencies: - compression "^1.6.2" - -micro@9.1.0: - version "9.1.0" - resolved "https://registry.yarnpkg.com/micro/-/micro-9.1.0.tgz#f2effba306639076e994c007c327dfc36a5185e9" - dependencies: - content-type "1.0.4" - is-stream "1.1.0" - mri "1.1.0" - raw-body "2.3.2" - micromatch@^2.1.5, micromatch@^2.3.11: version "2.3.11" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" @@ -8491,11 +8344,11 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.x.x, "mime-db@>= 1.33.0 < 2", mime-db@~1.33.0: +mime-db@1.x.x, mime-db@~1.33.0: version "1.33.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" -mime-types@2.1.18, mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7: +mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7: version "2.1.18" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" dependencies: @@ -8505,10 +8358,6 @@ mime@1.3.x: version "1.3.6" resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.6.tgz#591d84d3653a6b0b4a3b9df8de5aa8108e72e5e0" -mime@1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" - mime@^1.2.11, mime@^1.3.4, mime@^1.4.1: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -8668,10 +8517,6 @@ moment@2.x.x, "moment@>= 2.9.0", moment@^2.10.6, moment@^2.13.0, moment@^2.20.1: version "2.21.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.21.0.tgz#2a114b51d2a6ec9e6d83cf803f838a878d8a023a" -mri@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.0.tgz#5c0a3f29c8ccffbbb1ec941dcec09d71fa32f36a" - ms@0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.0.tgz#865be94c2e7397ad8a57da6a633a6e2f30798b83" @@ -8688,7 +8533,7 @@ ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" -ms@2.1.1, ms@^2.0.0: +ms@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" @@ -8891,10 +8736,6 @@ node-status-codes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-status-codes/-/node-status-codes-1.0.0.tgz#5ae5541d024645d32a58fcddc9ceecea7ae3ac2f" -node-version@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.1.0.tgz#f437d7ba407e65e2c4eaef8887b1718ba523d4f0" - nomnom@~1.6.2: version "1.6.2" resolved "https://registry.yarnpkg.com/nomnom/-/nomnom-1.6.2.tgz#84a66a260174408fc5b77a18f888eccc44fb6971" @@ -9118,10 +8959,6 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" -on-headers@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7" - once@1.x, once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.3.3, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -9138,16 +8975,6 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" -openssl-self-signed-certificate@1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/openssl-self-signed-certificate/-/openssl-self-signed-certificate-1.1.6.tgz#9d3a4776b1a57e9847350392114ad2f915a83dd4" - -opn@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/opn/-/opn-5.2.0.tgz#71fdf934d6827d676cecbea1531f95d354641225" - dependencies: - is-wsl "^1.1.0" - optimist@^0.6.1, optimist@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -9399,7 +9226,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1, path-is-absolute@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-is-inside@1.0.2, path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" @@ -9424,12 +9251,6 @@ path-to-regexp@^1.0.0, path-to-regexp@^1.7.0: dependencies: isarray "0.0.1" -path-type@3.0.0, path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - dependencies: - pify "^3.0.0" - path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -9444,6 +9265,12 @@ path-type@^2.0.0: dependencies: pify "^2.0.0" +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + dependencies: + pify "^3.0.0" + pause-stream@0.0.11: version "0.0.11" resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" @@ -9576,10 +9403,6 @@ pkg-up@^2.0.0: dependencies: find-up "^2.1.0" -pkginfo@0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff" - plugin-error@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/plugin-error/-/plugin-error-1.0.1.tgz#77016bd8919d0ac377fdcdd0322328953ca5781c" @@ -9915,10 +9738,6 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -prettier@^1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.11.1.tgz#61e43fc4cd44e68f2b0dfc2c38cd4bb0fccdcc75" - prettier@^1.12.1: version "1.12.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.12.1.tgz#c1ad20e803e7749faf905a409d2367e06bbe7325" @@ -10193,7 +10012,7 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -range-parser@^1.2.0, range-parser@~1.2.0: +range-parser@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" @@ -10737,6 +10556,9 @@ 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" @@ -11128,7 +10950,7 @@ rxjs@5.4.3: dependencies: symbol-observable "^1.0.1" -safe-buffer@5.1.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -11249,51 +11071,6 @@ semver@~5.0.1: version "5.0.3" resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" -send@0.16.2: - version "0.16.2" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.4.0" - -serve@^6.3.1: - version "6.5.3" - resolved "https://registry.yarnpkg.com/serve/-/serve-6.5.3.tgz#39ae7b7ff5934a9ca93ba7235344eb34b726cc48" - dependencies: - "@zeit/check-updates" "1.1.0" - args "3.0.8" - basic-auth "2.0.0" - bluebird "3.5.1" - boxen "1.3.0" - chalk "2.3.2" - clipboardy "1.2.3" - dargs "5.1.0" - detect-port "1.2.2" - filesize "3.6.0" - fs-extra "5.0.0" - handlebars "4.0.11" - ip "1.1.5" - micro "9.1.0" - micro-compress "1.0.0" - mime-types "2.1.18" - node-version "1.1.0" - openssl-self-signed-certificate "1.1.6" - opn "5.2.0" - path-is-inside "1.0.2" - path-type "3.0.0" - send "0.16.2" - set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -11768,7 +11545,7 @@ static-module@^2.2.0: static-eval "^2.0.0" through2 "~2.0.3" -statuses@1, "statuses@>= 1.2.1 < 2", "statuses@>= 1.3.1 < 2", statuses@~1.4.0: +statuses@1, "statuses@>= 1.2.1 < 2", "statuses@>= 1.3.1 < 2": version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" @@ -11840,12 +11617,6 @@ string-length@^2.0.0: astral-regex "^1.0.0" strip-ansi "^4.0.0" -string-similarity@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/string-similarity/-/string-similarity-1.2.0.tgz#d75153cb383846318b7a39a8d9292bb4db4e9c30" - dependencies: - lodash "^4.13.1" - string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -12743,7 +12514,19 @@ upath@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/upath/-/upath-1.0.4.tgz#ee2321ba0a786c50973db043a50b7bcba822361d" -update-notifier@2.3.0, update-notifier@^2.2.0: +update-notifier@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.5.0.tgz#07b5dc2066b3627ab3b4f530130f7eddda07a4cc" + dependencies: + chalk "^1.0.0" + configstore "^1.0.0" + is-npm "^1.0.0" + latest-version "^1.0.0" + repeating "^1.1.2" + semver-diff "^2.0.0" + string-length "^1.0.0" + +update-notifier@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.3.0.tgz#4e8827a6bb915140ab093559d7014e3ebb837451" dependencies: @@ -12757,18 +12540,6 @@ update-notifier@2.3.0, update-notifier@^2.2.0: semver-diff "^2.0.0" xdg-basedir "^3.0.0" -update-notifier@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-0.5.0.tgz#07b5dc2066b3627ab3b4f530130f7eddda07a4cc" - dependencies: - chalk "^1.0.0" - configstore "^1.0.0" - is-npm "^1.0.0" - latest-version "^1.0.0" - repeating "^1.1.2" - semver-diff "^2.0.0" - string-length "^1.0.0" - urix@^0.1.0, urix@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" @@ -12880,10 +12651,6 @@ value-or-function@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" -vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - vega-canvas@1: version "1.0.1" resolved "https://registry.yarnpkg.com/vega-canvas/-/vega-canvas-1.0.1.tgz#22cfa510af0cfbd920fc6af8b6111d3de5e63c44" From aa3abdd4e455cf0cfd633de165d0cfd5942d87dc Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Wed, 16 May 2018 20:20:07 -0400 Subject: [PATCH 11/62] Adding server api tests --- .../register_license_checker.js | 4 +- .../indices/__tests__/bootstrap_route.test.js | 56 +++++++++++++ .../__tests__/get_affected_route.test.js | 78 +++++++++++++++++++ .../indices/register_get_affected_route.js | 2 +- 4 files changed, 137 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/bootstrap_route.test.js create mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/get_affected_route.test.js 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 index b05946e60b330..35bc4b7533605 100644 --- 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 @@ -10,9 +10,9 @@ import { PLUGIN } from '../../../common/constants'; export function registerLicenseChecker(server) { const xpackMainPlugin = server.plugins.xpack_main; - const watcherPlugin = server.plugins.watcher; + const ilmPlugin = server.plugins.index_lifecycle_management; - mirrorPluginStatus(xpackMainPlugin, watcherPlugin); + mirrorPluginStatus(xpackMainPlugin, ilmPlugin); xpackMainPlugin.status.once('green', () => { // Register a function that is called whenever the xpack info changes, // to re-compute the license check results for this plugin diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/bootstrap_route.test.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/bootstrap_route.test.js new file mode 100644 index 0000000000000..5bc48358cd187 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/bootstrap_route.test.js @@ -0,0 +1,56 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under 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'; + +jest.mock('../../../../lib/call_with_request_factory', () => { + const mock = jest.fn(); + return { + callWithRequestFactory: () => mock, + }; +}); + +jest.mock('../../../../lib/is_es_error_factory', () => ({ + isEsErrorFactory: jest.fn().mockImplementation(() => jest.fn()), +})); + +jest.mock('../../../../lib/license_pre_routing_factory', () => ({ + licensePreRoutingFactory: jest.fn().mockImplementation(() => jest.fn()), +})); + +let routeHandler; +const mockServer = { + route: options => { + routeHandler = options.handler; + } +}; + +describe('ilmBootstrapRoute', () => { + it('should call indices.create', async () => { + registerBootstrapRoute(mockServer); + + await routeHandler({ payload: { + indexName: 'myIndex', + aliasName: 'myAlias', + } }, jest.fn()); + + const mock = require('../../../../lib/call_with_request_factory').callWithRequestFactory().mock; + + expect(mock.calls.length).toBe(1); + expect(mock.calls[0]).toEqual([ + 'indices.create', + { + index: 'myIndex', + aliases: { + myAlias: {} + }, + settings: { + 'index.lifecycle.rollover_alias': 'myAlias' + } + } + ]); + }); +}); diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/get_affected_route.test.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/get_affected_route.test.js new file mode 100644 index 0000000000000..f50ede9e34af7 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/get_affected_route.test.js @@ -0,0 +1,78 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under 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 { registerGetAffectedRoute } from '../register_get_affected_route'; + +jest.mock('../../../../lib/call_with_request_factory', () => { + const mock = jest.fn().mockImplementation((method, params) => { + // console.log('hi', method, params); + if (params.path === '/_template') { + return { + 'foobar': { + index_patterns: ['foobar*'] + }, + 'barfoo': { + index_patterns: ['barfoo*'], + settings: { + index: { + lifecycle: { + name: 'myPolicy' + } + } + } + } + }; + } + }); + return { + callWithRequestFactory: () => mock, + }; +}); + +jest.mock('../../../../lib/is_es_error_factory', () => ({ + isEsErrorFactory: jest.fn().mockImplementation(() => jest.fn()), +})); + +jest.mock('../../../../lib/license_pre_routing_factory', () => ({ + licensePreRoutingFactory: jest.fn().mockImplementation(() => jest.fn()), +})); + +const routeHandlers = []; +const mockServer = { + route: options => { + routeHandlers.push(options.handler); + } +}; + +describe('ilmGetAffectedRoute', () => { + it('should call indices.create', async () => { + registerGetAffectedRoute(mockServer); + + + for (const routeHandler of routeHandlers) { + await routeHandler({ params: { + indexTemplateName: 'foobar', + policyName: 'myPolicy' + } }, jest.fn()); + } + + const mock = require('../../../../lib/call_with_request_factory').callWithRequestFactory().mock; + + expect(mock.calls.length).toBe(4); + expect(mock.calls[1]).toEqual([ + 'indices.get', + { + index: ['foobar*'] + } + ]); + expect(mock.calls[3]).toEqual([ + 'indices.get', + { + index: ['foobar*', 'barfoo*'] + } + ]); + }); +}); 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 0cb74ac6d2599..fc7f5f2d2d131 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 @@ -27,7 +27,7 @@ async function getAffectedIndices( ) { const templates = await fetchTemplates(callWithRequest); - if (!templates || templates.length === 0) { + if (!templates || Object.keys(templates).length === 0) { return []; } From 70caea4db1a8cedab4b59182f952a08563dbc485 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Thu, 17 May 2018 11:07:16 -0400 Subject: [PATCH 12/62] Removing debug and some tweaks from dave's work --- .../public/api/index.js | 2 -- .../public/lib/diff_ace_addons.js | 22 ++-------------- .../public/lib/diff_tools.js | 4 --- .../components/cold_phase/cold_phase.js | 2 +- .../components/delete_phase/delete_phase.js | 2 +- .../components/hot_phase/hot_phase.js | 2 +- .../components/warm_phase/warm_phase.js | 2 +- .../policy_selection/policy_selection.js | 16 +++++++----- .../wizard/components/review/diff_view.js | 6 ----- .../wizard/components/review/review.js | 2 -- .../public/store/actions/index_template.js | 4 +-- .../public/store/actions/policies.js | 1 + .../public/store/middleware/index.js | 1 + ..._selected_policy_from_selected_template.js | 26 +++++++++++++++++++ .../public/store/reducers/policies.js | 2 +- .../public/store/store.js | 4 +-- .../__tests__/get_affected_route.test.js | 1 - 17 files changed, 48 insertions(+), 51 deletions(-) create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/middleware/set_selected_policy_from_selected_template.js 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 c82f07b7d6556..c771697e6b27a 100644 --- a/x-pack/plugins/index_lifecycle_management/public/api/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/api/index.js @@ -11,8 +11,6 @@ export const setHttpClient = (client) => { }; const apiPrefix = chrome.addBasePath('/api/index_lifecycle_management'); -console.log('apiPrefix', apiPrefix); - export async function loadNodes() { const response = await httpClient.get(`${apiPrefix}/nodes/list`); return response.data; diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js b/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js index 31e64a3c5b1d7..96d3f1cc6849f 100644 --- a/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js +++ b/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js @@ -7,30 +7,22 @@ import ace from 'brace'; import { ADDITION_PREFIX, REMOVAL_PREFIX } from './diff_tools'; function findInObject(key, obj, debug) { - // debug && console.log('findInObject()', key, obj); const objKeys = Object.keys(obj); for (const objKey of objKeys) { if (objKey === key) { - // debug && console.log('findInObject() FOUND', key); return obj[objKey]; } if (typeof obj[objKey] === 'object' && !Array.isArray(obj[objKey])) { const item = findInObject(key, obj[objKey], debug); if (item !== false) { - // debug && console.log('findInObject() FOUND 2', key); return item; } } } - // debug && console.log('findInObject() NOT FOUND', key); return false; } function getDiffClasses(key, val, jsonObject) { - const debug = false;//key === 'name' && val === '"t"'; - - debug && console.log('getDiffClasses()', key, val); - let value = val; if (value.endsWith(',')) { value = value.slice(0, -1); @@ -39,8 +31,8 @@ function getDiffClasses(key, val, jsonObject) { value = value.slice(1, -1); } - const additionValue = findInObject(`${ADDITION_PREFIX}${key}`, jsonObject, debug); - const removalValue = findInObject(`${REMOVAL_PREFIX}${key}`, jsonObject, debug); + const additionValue = findInObject(`${ADDITION_PREFIX}${key}`, jsonObject); + const removalValue = findInObject(`${REMOVAL_PREFIX}${key}`, jsonObject); const isAddition = Array.isArray(additionValue) ? !!additionValue.find(v => v === value) @@ -58,16 +50,6 @@ function getDiffClasses(key, val, jsonObject) { diffClasses = 'variable'; } - debug && console.log(`getDiffClasses() - key='${key}' - value='${value}' - additionValue='${additionValue}' - removalValue='${removalValue}' - isAddition=${isAddition} - isRemoval=${isRemoval} - diffClasses='${diffClasses}' - `); - return diffClasses; } diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js b/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js index 30e4dacbb3cfb..ca2b113c83086 100644 --- a/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js +++ b/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js @@ -95,10 +95,7 @@ export const mergeAndPreserveDuplicateKeys = ( changes = [] ) => { for (const [key, value] of Object.entries(source)) { - // const debug = key === 'fooobar'; - // debug && console.log('mergeAndPreserveDuplicateKeys', key, value, target); if (isDifferent(target, key, value)) { - // debug && console.log('isDifferent'); result[`${REMOVAL_PREFIX}${key}`] = value; result[`${ADDITION_PREFIX}${key}`] = target[key]; changes.push({ @@ -107,7 +104,6 @@ export const mergeAndPreserveDuplicateKeys = ( updated: removePrefixes(target[key]), }); } else if (isObject(value)) { - // debug && console.log('value is object', target[key]); if (target.hasOwnProperty(key)) { const recurseResult = mergeAndPreserveDuplicateKeys(value, target[key]); result[key] = recurseResult.result; 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 index 13f73ce68b5a7..65e9876fd88b8 100644 --- 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 @@ -82,7 +82,7 @@ export class ColdPhase extends PureComponent {
Cold phase{' '} {phaseData[PHASE_ENABLED] ? ( - + ) : null}
} 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 index 7a8a00301023e..40974abb33fec 100644 --- 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 @@ -65,7 +65,7 @@ export class DeletePhase extends PureComponent {
Delete phase{' '} {phaseData[PHASE_ENABLED] ? ( - + ) : null}
} 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 index 9511cdac48294..89d893dbc070f 100644 --- 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 @@ -70,7 +70,7 @@ export class HotPhase extends PureComponent { title={
Hot phase{' '} - +
} titleSize="s" 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 index c627b96bd2a0a..56418c4ea34f4 100644 --- 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 @@ -116,7 +116,7 @@ export class WarmPhase extends Component {
Warm phase{' '} {phaseData[PHASE_ENABLED] ? ( - + ) : null}
} 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 index 80e10110baa1b..2f5e71d8d0f42 100644 --- 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 @@ -31,7 +31,8 @@ export class PolicySelection extends Component { this.props.fetchPolicies(); } - selectPolicy(policy) { + selectPolicy(policyName) { + const policy = this.props.policies.find(policy => policy.name === policyName); this.props.setSelectedPolicy(policy); // this.props.done(); } @@ -40,10 +41,11 @@ export class PolicySelection extends Component { render() { const { policies, existingPolicyName } = this.props; - let options = []; - options = policies.map(item => ({ value: item.name, text: item.name })); - - console.log(policies); + const options = policies.map(item => ({ value: item.name, text: item.name })); + options.unshift({ + value: '', + text: '-- New Policy --' + }); return ( - + this.selectPolicy(null)} + onClick={() => this.selectPolicy()} > Create new 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 index 7f743e048fd46..a89f7e2412c59 100644 --- 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 @@ -47,22 +47,16 @@ export class DiffView extends PureComponent { templateDiff: { originalFullIndexTemplate, newFullIndexTemplate }, } = this.props; - // console.log(JSON.stringify(this.props)); - const { result: mergedJson, changes } = mergeAndPreserveDuplicateKeys( originalFullIndexTemplate, newFullIndexTemplate ); - console.log('mergedJson', mergedJson, changes); - // Strip the ^ and $ characters const mergedJsonAsString = removePrefixes( JSON.stringify(mergedJson, null, 2) ); - // console.log('mergedJsonAsString', mergedJsonAsString); - setCurrentJsonObject(mergedJson); addDiffAddonsForAce(); 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 fff16b7af2bb4..98a4ca16dc609 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 @@ -133,8 +133,6 @@ export class Review extends Component { const { affectedIndices, isLoadingAffectedIndices, isShowingErrors } = this.state; - // console.log('render', affectedIndices); - return (
{/* 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 index 50eec52976059..a7640e9cfb97f 100644 --- 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 @@ -17,7 +17,7 @@ import { setAliasName, setSelectedPrimaryShardCount, setSelectedReplicaCount, - setSelectedNodeAttrs + setSelectedNodeAttrs, } from '.'; import { PHASE_HOT, @@ -43,7 +43,7 @@ export const fetchIndexTemplates = () => async dispatch => { }; export const fetchedIndexTemplate = createAction('FETCHED_INDEX_TEMPLATE'); -export const fetchIndexTemplate = templateName => async dispatch => { +export const fetchIndexTemplate = templateName => async (dispatch) => { let template; try { template = await loadIndexTemplate(templateName); 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 47046331a4eb4..7d420d6e43b20 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,6 +22,7 @@ export const fetchPolicies = () => async dispatch => { } dispatch(fetchedPolicies(policies)); + return policies; }; export const setSelectedPolicy = createAction('SET_SELECTED_POLICY'); diff --git a/x-pack/plugins/index_lifecycle_management/public/store/middleware/index.js b/x-pack/plugins/index_lifecycle_management/public/store/middleware/index.js index ccad9cac1daa4..1ec89365a7906 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/middleware/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/middleware/index.js @@ -5,3 +5,4 @@ */ export { autoEnablePhase } from './auto_enable_phase'; +export { setSelectedPolicyFromSelectedTemplate } from './set_selected_policy_from_selected_template'; 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 new file mode 100644 index 0000000000000..f9ab711e9f302 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/store/middleware/set_selected_policy_from_selected_template.js @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under 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 +} from '../actions'; + +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)); + } + } + } + + 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 91e6e255e0859..982b20381dc50 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 @@ -112,7 +112,7 @@ export const policies = handleActions( }; }, [setSelectedPolicy](state, { payload: selectedPolicy }) { - if (selectedPolicy === null) { + if (!selectedPolicy) { return { ...state, selectedPolicy: defaultPolicy, 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 355a834188f3f..024f8bcd81634 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/store.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/store.js @@ -8,10 +8,10 @@ import { createStore, applyMiddleware, compose } from 'redux'; import thunk from 'redux-thunk'; import { indexLifecycleManagement } from './reducers/'; -import { autoEnablePhase } from './middleware'; +import { autoEnablePhase, setSelectedPolicyFromSelectedTemplate } from './middleware'; export const indexLifecycleManagementStore = (initialState = {}) => { - const enhancers = [ applyMiddleware(thunk, autoEnablePhase) ]; + const enhancers = [ applyMiddleware(thunk, autoEnablePhase, setSelectedPolicyFromSelectedTemplate) ]; window.__REDUX_DEVTOOLS_EXTENSION__ && enhancers.push(window.__REDUX_DEVTOOLS_EXTENSION__()); return createStore( diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/get_affected_route.test.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/get_affected_route.test.js index f50ede9e34af7..67c5865ba1a75 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/get_affected_route.test.js +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/get_affected_route.test.js @@ -8,7 +8,6 @@ import { registerGetAffectedRoute } from '../register_get_affected_route'; jest.mock('../../../../lib/call_with_request_factory', () => { const mock = jest.fn().mockImplementation((method, params) => { - // console.log('hi', method, params); if (params.path === '/_template') { return { 'foobar': { From bb15a2687d804dc15ee99a0c1338d95a219f79ce Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Thu, 17 May 2018 11:40:20 -0400 Subject: [PATCH 13/62] Conditionally show this message --- .../components/review/review.container.js | 2 ++ .../wizard/components/review/review.js | 28 ++++++++++++------- 2 files changed, 20 insertions(+), 10 deletions(-) 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 index 6c4ee3b274347..dbc2fcae7f535 100644 --- 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 @@ -20,6 +20,7 @@ import { getAliasName, getBootstrapEnabled, getIndexName, + getPolicies, } from '../../../../store/selectors'; import { setSelectedPolicyName, @@ -33,6 +34,7 @@ export const Review = connect( state => ({ selectedIndexTemplateName: getSelectedIndexTemplateName(state), affectedIndexTemplates: getAffectedIndexTemplates(state), + policies: getPolicies(state), templateDiff: getTemplateDiff(state), lifecycle: getLifecycle(state), bootstrapEnabled: getBootstrapEnabled(state), 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 98a4ca16dc609..72e2f9319b61f 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 @@ -79,7 +79,7 @@ export class Review extends Component { this.props.selectedPolicyName ); this.setState({ affectedIndices, isLoadingAffectedIndices: false }); - }, 500); + }, 1000); } async componentWillMount() { @@ -129,10 +129,14 @@ export class Review extends Component { lifecycle, bootstrapEnabled, aliasName, + policies, } = this.props; const { affectedIndices, isLoadingAffectedIndices, isShowingErrors } = this.state; + const showSaveChangedMessage = (originalPolicyName && !saveAsNewPolicy) + || (saveAsNewPolicy && !!policies.find(policy => policy.name === selectedPolicyName)); + return (
{/* @@ -217,18 +221,22 @@ export class Review extends Component { {originalPolicyName ? ( - -

Save changes to {originalPolicyName} policy

-
- -

- You are editing an existing policy. This means that any saves you make + { showSaveChangedMessage ? ( + + +

Save changes to {selectedPolicyName} policy

+
+ +

+ You are editing an existing policy. This means that any saves you make will also change any index templates this policy is attached to. You can instead save these changes and make it a brand new policy that only changes the template you selected. -

-
- +

+ + + + ) : null } Date: Fri, 18 May 2018 10:12:22 -0400 Subject: [PATCH 14/62] Policy selection cleanup --- .../policy_selection/policy_selection.container.js | 4 ++-- .../components/policy_selection/policy_selection.js | 8 ++++---- .../public/store/actions/index_template.js | 4 ++++ .../public/store/selectors/index_template.js | 8 -------- 4 files changed, 10 insertions(+), 14 deletions(-) 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 index abe56ef4db032..618cd3a128bbc 100644 --- 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 @@ -10,7 +10,7 @@ import { connect } from 'react-redux'; import { PolicySelection as PresentationComponent } from './policy_selection'; import { - getPolicies, getExistingPolicyName, + getPolicies, getSelectedPolicyName, } from '../../../../store/selectors'; import { fetchPolicies, @@ -20,7 +20,7 @@ import { export const PolicySelection = connect( state => ({ policies: getPolicies(state), - existingPolicyName: getExistingPolicyName(state), + selectedPolicyName: getSelectedPolicyName(state), }), { fetchPolicies, 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 index 2f5e71d8d0f42..c5d63fbd61fec 100644 --- 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 @@ -23,7 +23,7 @@ export class PolicySelection extends Component { // done: PropTypes.func.isRequired, // back: PropTypes.func.isRequired, - existingPolicyName: PropTypes.string.isRequired, + selectedPolicyName: PropTypes.string.isRequired, policies: PropTypes.array.isRequired }; @@ -39,7 +39,7 @@ export class PolicySelection extends Component { render() { - const { policies, existingPolicyName } = this.props; + const { policies, selectedPolicyName } = this.props; const options = policies.map(item => ({ value: item.name, text: item.name })); options.unshift({ @@ -62,7 +62,7 @@ export class PolicySelection extends Component { { await this.selectPolicy(e.target.value); }} @@ -101,7 +101,7 @@ export class PolicySelection extends Component {

{item.name} - {existingPolicyName === item.name ? '*' : ''} + {selectedPolicyName === item.name ? '*' : ''}

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 index a7640e9cfb97f..c7bcd3518d036 100644 --- 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 @@ -18,6 +18,7 @@ import { setSelectedPrimaryShardCount, setSelectedReplicaCount, setSelectedNodeAttrs, + setSelectedPolicyName, } from '.'; import { PHASE_HOT, @@ -69,6 +70,9 @@ export const fetchIndexTemplate = templateName => async (dispatch) => { ) ); } + if (template.settings.index.lifecycle) { + dispatch(setSelectedPolicyName(template.settings.index.lifecycle.name)); + } } let indexPattern = template.index_patterns[0]; 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 c99fb716e4761..9992c7491d368 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 @@ -57,14 +57,6 @@ export const getSelectedIndexTemplate = createSelector( 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) { From 2ad2735081b25269e13043506d0479792f36ec8c Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Fri, 18 May 2018 15:50:28 -0400 Subject: [PATCH 15/62] Updates for better UX --- .../components/warm_phase/warm_phase.js | 2 + .../store/middleware/auto_set_node_attrs.js | 34 ++++++++++++++ .../public/store/middleware/index.js | 1 + ..._selected_policy_from_selected_template.js | 18 +++++++- .../public/store/selectors/lifecycle.js | 45 ++++++++++++++++--- .../public/store/store.js | 18 ++++++-- 6 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/middleware/auto_set_node_attrs.js 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 index 56418c4ea34f4..71aa73ea8bcaf 100644 --- 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 @@ -110,6 +110,8 @@ export class WarmPhase extends Component { hotPhaseRolloverEnabled, } = this.props; + console.log('warm', phaseData, phaseData[PHASE_NODE_ATTRS]); + return ( next => action => { + const state = store.getState(); + + if (action.type === setSelectedNodeAttrs().type) { + 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 === setPhaseData().type) { + 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/index.js b/x-pack/plugins/index_lifecycle_management/public/store/middleware/index.js index 1ec89365a7906..fcb0a960db4e2 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/middleware/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/middleware/index.js @@ -6,3 +6,4 @@ export { autoEnablePhase } from './auto_enable_phase'; export { setSelectedPolicyFromSelectedTemplate } from './set_selected_policy_from_selected_template'; +export { autoSetNodeAttrs } from './auto_set_node_attrs'; 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 index f9ab711e9f302..a87f9c3496d64 100644 --- 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 @@ -7,8 +7,11 @@ import { fetchedIndexTemplate, fetchPolicies, - setSelectedPolicy + 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) { @@ -18,6 +21,19 @@ export const setSelectedPolicyFromSelectedTemplate = store => next => async acti 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)); + } } } } 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 a34e94af5c6ab..af92c797b8df4 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 @@ -27,7 +27,9 @@ import { PHASE_ATTRIBUTES_THAT_ARE_NUMBERS, PHASE_PRIMARY_SHARD_COUNT, PHASE_SHRINK_ENABLED, - STRUCTURE_REVIEW + STRUCTURE_REVIEW, + PHASE_FORCE_MERGE_ENABLED, + PHASE_FORCE_MERGE_SEGMENTS } from '../constants'; import { getPhase, @@ -84,6 +86,24 @@ export const validatePhase = (type, phase) => { } } + if (phase[PHASE_SHRINK_ENABLED]) { + 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 (phase[PHASE_FORCE_MERGE_ENABLED]) { + if (!isNumber(phase[PHASE_FORCE_MERGE_SEGMENTS])) { + errors[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.']; + } + } + return errors; }; @@ -142,23 +162,38 @@ export const validateLifecycle = state => { // } // } + const hotPhase = getPhase(state, PHASE_HOT); + const warmPhase = getPhase(state, PHASE_WARM); + 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, getPhase(state, PHASE_HOT)) + ...validatePhase(PHASE_HOT, hotPhase) }; errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_WARM] = { ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_WARM], - ...validatePhase(PHASE_WARM, getPhase(state, PHASE_WARM)) + ...validatePhase(PHASE_WARM, warmPhase) }; errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_COLD] = { ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_COLD], - ...validatePhase(PHASE_COLD, getPhase(state, PHASE_COLD)) + ...validatePhase(PHASE_COLD, coldPhase) }; errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_DELETE] = { ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_DELETE], - ...validatePhase(PHASE_DELETE, getPhase(state, PHASE_DELETE)) + ...validatePhase(PHASE_DELETE, deletePhase) }; + 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( + '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/store.js b/x-pack/plugins/index_lifecycle_management/public/store/store.js index 024f8bcd81634..2e3b5c219dad8 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/store.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/store.js @@ -4,14 +4,24 @@ * you may not use this file except in compliance with the Elastic License. */ -import { createStore, applyMiddleware, compose } from 'redux'; +import { + createStore, + applyMiddleware, + compose +} from 'redux'; import thunk from 'redux-thunk'; -import { indexLifecycleManagement } from './reducers/'; -import { autoEnablePhase, setSelectedPolicyFromSelectedTemplate } from './middleware'; +import { + indexLifecycleManagement +} from './reducers/'; +import { + autoEnablePhase, + setSelectedPolicyFromSelectedTemplate, + autoSetNodeAttrs +} from './middleware'; export const indexLifecycleManagementStore = (initialState = {}) => { - const enhancers = [ applyMiddleware(thunk, autoEnablePhase, setSelectedPolicyFromSelectedTemplate) ]; + const enhancers = [applyMiddleware(thunk, autoEnablePhase, setSelectedPolicyFromSelectedTemplate, autoSetNodeAttrs)]; window.__REDUX_DEVTOOLS_EXTENSION__ && enhancers.push(window.__REDUX_DEVTOOLS_EXTENSION__()); return createStore( From 877d84934d22c0a990d954ec0cd8860a126c3289 Mon Sep 17 00:00:00 2001 From: gchaps Date: Mon, 21 May 2018 11:54:11 -0700 Subject: [PATCH 16/62] [COPYEDIT | ILM] Copyedit of text in index lifecycle management UI --- .../components/configuration/configuration.js | 8 +++--- .../template_selection/template_selection.js | 6 ++--- .../index_template/index_template.js | 2 +- .../components/cold_phase/cold_phase.js | 8 +++--- .../components/delete_phase/delete_phase.js | 4 +-- .../components/hot_phase/hot_phase.js | 11 ++++---- .../components/warm_phase/warm_phase.js | 19 +++++++------- .../policy_configuration.js | 6 ++--- .../wizard/components/review/review.js | 22 ++++++++-------- .../public/sections/wizard/wizard.js | 2 +- .../public/store/selectors/lifecycle.js | 26 +++++++++---------- 11 files changed, 57 insertions(+), 57 deletions(-) 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 index 99a5899dd5efe..707bf4d9dcad2 100644 --- 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 @@ -92,9 +92,9 @@ export class Configuration extends Component { return (
Configuration} + title={

Configure hot indices

} titleSize="s" - description="Indices are thought of as "hot" when they are actively being written to." + description="A hot index is actively being written to." fullWidth > - Learn more in our docs - . + Learn more +

} /> 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 index 3d5777711a555..29a1430a4b17b 100644 --- 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 @@ -68,7 +68,7 @@ export class TemplateSelection extends PureComponent { when you create an index.{' '} Learn more - . +

} > @@ -100,7 +100,7 @@ export class TemplateSelection extends PureComponent { {bootstrapEnabled ? (

- Your read-only index is queried less frequently. Use this phase - when the index no longer needs to be on the most performant hardware. + Your index is queried less frequently + and no longer needs to be on the most performant hardware.

{isShowingErrors ? ( -

This phase contains errors that need to be fixed.

+

This phase contains errors

) : null} @@ -206,7 +206,7 @@ export class ColdPhase extends PureComponent { setPhaseData(PHASE_REPLICA_COUNT, warmPhaseReplicaCount) } > - Set same as warm phase + Set to same as warm phase 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 index 40974abb33fec..7c674116c0fa6 100644 --- 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 @@ -73,12 +73,12 @@ export class DeletePhase extends PureComponent { description={

- When your data is no longer useful. Define how long you want to retain it. + Use this phase to define how long to retain your data.

{isShowingErrors ? ( -

This phase contains errors that need to be fixed.

+

This phase contains errors

) : null} 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 index 89d893dbc070f..2510e264f9395 100644 --- 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 @@ -77,12 +77,13 @@ export class HotPhase extends PureComponent { description={

- This phase is required. Your index is being queried and in active writing mode. + This phase is required. Your index is being queried and actively written to. + You can optimize this phase for write throughput.

{isShowingErrors ? ( -

This phase contains errors that need to be fixed.

+

This phase contains errors

) : null} @@ -94,9 +95,9 @@ export class HotPhase extends PureComponent { hasEmptyLabelSpace helpText={

- Setting this to true will rollover the index when it gets too big or too old. The alias will switch to the new index.{' '} + If true, rollover the index when it gets too big or too old. The alias switches to the new index.{' '} - Learn more. + Learn more

} @@ -116,7 +117,7 @@ export class HotPhase extends PureComponent {

- Your index is frequently queried, but is read-only. - Use this phase to optimize for search.Your index is being queried - and in active writing mode. + Your index becomes read-only when it enters the warm phase. + You can optimize this phase for search.

{isShowingErrors ? ( -

This phase contains errors that need to be fixed.

+

This phase contains errors

) : null} @@ -267,7 +266,7 @@ export class WarmPhase extends Component { validate(); }} > - Set same as hot phase + Set to same as hot phase
@@ -282,7 +281,7 @@ export class WarmPhase extends Component { Shrink the index into a new index with fewer primary shards.{' '} - Learn more. + Learn more @@ -295,7 +294,7 @@ export class WarmPhase extends Component { await setPhaseData(PHASE_SHRINK_ENABLED, e.target.checked); validate(); }} - label="Enable shrink" + label="Shrink index" /> @@ -334,7 +333,7 @@ export class WarmPhase extends Component { validate(); }} > - Set same as hot phase + Set to same as hot phase @@ -349,10 +348,10 @@ export class WarmPhase extends Component { - Reduce the number of segments in your shard by and merging smaller + Reduce the number of segments in your shard by merging smaller files and clearing deleted ones.{' '} - Learn More + Learn more 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 index 8cabbf599371e..eacadcba7fd6a 100644 --- 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 @@ -72,7 +72,7 @@ export class PolicyConfiguration extends Component { if (await this.validate()) { this.props.done(); } else { - toastNotifications.addDanger('Please fix errors on the page.'); + toastNotifications.addDanger('Please the fix errors on the page'); } }; @@ -124,12 +124,12 @@ export class PolicyConfiguration extends Component {

- {!selectedPolicyName ? 'Create a new policy' : `Edit policy ${selectedPolicyName}`} + {!selectedPolicyName ? 'Create a policy' : `Edit policy ${selectedPolicyName}`}

-

Configure the phases of your data and when to transition between them. Only the hot phase is required.

+

Configure the phases of your data and when to transition between them.

Review your policy changes -

Be careful. Your changes will go into effect immediately once you save.

+

When you save a policy, your changes go into effect immediately.

-

{`${affectedIndexTemplates.length} Affected index ${affectedIndexTemplates.length === 1 ? 'template' : 'templates'}`}

+

{`${affectedIndexTemplates.length} Index ${affectedIndexTemplates.length === 1 ? 'template' : 'templates'}`}

    {affectedIndexTemplates.map(template => (
  • {template}
  • ))}
-

{`${affectedIndices.length} Affected ${affectedIndices.length === 1 ? 'Index' : 'Indices' }`}

+

{`${affectedIndices.length} ${affectedIndices.length === 1 ? 'Index' : 'Indices' }`}

{ isLoadingAffectedIndices ? ( ) : ( @@ -177,10 +177,10 @@ export class Review extends Component { -

Since you decided to bootstrap a new index you'll want to point to a new alias going forward

+

You decided to bootstrap a new index. Point to this new alias going forward.

{aliasName} is your new alias

@@ -224,13 +224,13 @@ export class Review extends Component { { showSaveChangedMessage ? ( -

Save changes to {selectedPolicyName} policy

+

Save changes to {selectedPolicyName} policy?

- You are editing an existing policy. This means that any saves you make - will also change any index templates this policy is attached to. You can instead save - these changes and make it a brand new policy that only changes the template you + 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 template you selected.

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 index 3a7ba64893b23..757326c6ed1d2 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js @@ -144,7 +144,7 @@ export class Wizard extends Component { // onClick: () => this.onSelectedStepChanged(2), // }, { - title: 'Configure policy', + title: 'Configure a policy', isSelected: this.state.selectedStep === 2, isComplete: this.state.selectedStep > 2, disabled: this.state.selectedStep < 2, 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 a34e94af5c6ab..0b3b97f7d83b9 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 @@ -58,10 +58,10 @@ export const validatePhase = (type, phase) => { !isNumber(phase[PHASE_ROLLOVER_MAX_SIZE_STORED]) ) { errors[PHASE_ROLLOVER_MAX_AGE] = [ - 'A rollover requires a max age, max docs, or max size.' + 'A maximum age is required' ]; errors[PHASE_ROLLOVER_MAX_SIZE_STORED] = [ - 'A rollover requires a max age, max docs, or max size.' + 'A maximum index size is required' ]; } } @@ -73,13 +73,13 @@ export const validatePhase = (type, phase) => { continue; } if (!isNumber(phase[numberedAttribute])) { - errors[numberedAttribute] = ['A number is required.']; + errors[numberedAttribute] = ['A number is required']; } else if (phase[numberedAttribute] < 0) { - errors[numberedAttribute] = ['Only positive numbers allowed.']; + errors[numberedAttribute] = ['Only positive numbers are allowed']; } else if (numberedAttribute === PHASE_PRIMARY_SHARD_COUNT && phase[numberedAttribute] < 1) { - errors[numberedAttribute] = ['Only positive numbers above 0 are allowed.']; + errors[numberedAttribute] = ['Only positive numbers are allowed']; } } } @@ -98,41 +98,41 @@ export const validateLifecycle = state => { } if (getBootstrapEnabled(state) && !getIndexName(state)) { - errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][STRUCTURE_INDEX_NAME].push('An index name is required.'); + errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][STRUCTURE_INDEX_NAME].push('An index name is required'); } if (getBootstrapEnabled(state) && !getAliasName(state)) { - errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][STRUCTURE_ALIAS_NAME].push('An alias name is required.'); + errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][STRUCTURE_ALIAS_NAME].push('An alias name is required'); } if (!isNumber(getSelectedPrimaryShardCount(state))) { errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][ STRUCTURE_PRIMARY_NODES - ].push('A value is required.'); + ].push('A value is required'); } else if (getSelectedPrimaryShardCount(state) < 1) { errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][ STRUCTURE_PRIMARY_NODES - ].push('Only positive numbers above 0 are allowed.'); + ].push('Only positive numbers are allowed'); } if (!isNumber(getSelectedReplicaCount(state))) { errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][ STRUCTURE_REPLICAS - ].push('A value is required.'); + ].push('A value is required'); } else if (getSelectedReplicaCount(state) < 0) { errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_CONFIGURATION][ STRUCTURE_REPLICAS - ].push('Only positive numbers allowed.'); + ].push('Only positive numbers are allowed'); } if (!getSelectedPolicyName(state)) { - errors[STRUCTURE_REVIEW][STRUCTURE_POLICY_NAME].push('A policy name is required.'); + errors[STRUCTURE_REVIEW][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_REVIEW][STRUCTURE_POLICY_NAME].push('The policy name must be different'); } // if (getSaveAsNewPolicy(state)) { From 374c6c4f9d413a136d084896df10be908138682a Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Tue, 29 May 2018 10:34:14 -0400 Subject: [PATCH 17/62] Use better default text --- .../index_lifecycle_management/public/store/selectors/nodes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index ca0d06f9f2dde..4a65cf969bdb5 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/nodes.js @@ -21,7 +21,7 @@ export const getNodeOptions = createSelector( options.sort((a, b) => a.value.localeCompare(b.value)); options.unshift({ - text: '', + text: '-- Do not reallocate my indices --', value: undefined, }); From f81799059b774e60b0d030f0815aeacc3fe19695 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Wed, 6 Jun 2018 09:41:34 -0400 Subject: [PATCH 18/62] Remove debug --- .../policy_configuration/components/warm_phase/warm_phase.js | 2 -- 1 file changed, 2 deletions(-) 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 index 55edac604eafd..5af74cf85e57f 100644 --- 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 @@ -110,8 +110,6 @@ export class WarmPhase extends Component { hotPhaseRolloverEnabled, } = this.props; - console.log('warm', phaseData, phaseData[PHASE_NODE_ATTRS]); - return ( Date: Mon, 11 Jun 2018 13:15:36 -0400 Subject: [PATCH 19/62] Adding readme and comments --- .../index_lifecycle_management/README.md | 70 +++++++++++++++++++ .../public/lib/diff_ace_addons.js | 23 ++++++ .../public/lib/diff_tools.js | 48 +++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 x-pack/plugins/index_lifecycle_management/README.md diff --git a/x-pack/plugins/index_lifecycle_management/README.md b/x-pack/plugins/index_lifecycle_management/README.md new file mode 100644 index 0000000000000..304a2f970a6d9 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/README.md @@ -0,0 +1,70 @@ +# Index lifecyle management + +## What is it +-- TODO -- + +## UI + +The UI currently consists of a single wizard, broken into three steps. + +### Step 1 +The first step involves choosing the index template in which the created/selected policy will be applied. +Then, it lets the user tweak configuration options on this template including shard and replica count as well as allocation rules. + +### Step 2 +The second step lets the user choose which policy they want to apply to the selected index template. They can choose a new one or select an existing one. Either way, after selection, they will see configuration options for the policy itself. This includes configuration for the hot, warm, cold, and delete phase. + +### Step 3 +The third and last step lets the user name their policy and also see the affected indices and index templates. These indices and index templates are what will be affected once the user saves the work done in the wizard (This includes changes to the index template itself which will change indices created from the template and also changes to a policy that is attached to another index template). The user can also see a visual diff of what will change in the index template. Then, the user clicks the Save button and blamo! + +## UI Architecture + +The UI is built on React and Redux. + +### Redux + +The redux store consists of a few top level attributes: +``` +indexTemplate +nodes +policies +general +``` + +The logic behind the store is separate into four main concerns: +1) reducers/ +2) actions/ +3) selectors/ +4) middleware/ + +The reducers and actions are pretty standard redux, so no need to discuss much there. + +### Selectors + +The selectors showcase how we access any stateful data. All access comes through selectors so if there are any changes required to the state tree, we only need to update the reducers and selectors. + +#### Middleware + +The middleware folder contains specific pieces of state logic we need to handle side effects of certain state changing. + +One example is the `auto_enable_phase.js` middleware. By default, the warm, cold and delete phases are disabled. However, the user can expand the section in the UI and edit configuration without needing to enable/disable the phase. Ideally, once the user edits any configuration piece within a phase, we _assume_ they want that phase enabled so this middleware will detect a change in a phase and enable if it is not enabled already. + +#### Generic phase data + +Each of our four phases have some similar and some unique configuration options. Instead of making each individual phase a specific action for that phase, the code is written more generically to capture any data change within a phase to a single action. Therefore, each phase component's configuration inputs will look similar, like: `setPhaseData(PHASE_ROLLOVER_AFTER_UNITS, e.target.value)`. The top level container for each phase will handle automatically prefixing the `setPhaseData` prop with the right phase: ` setPhaseData: (key, value) => setPhaseData(PHASE_COLD, key, value),` + +### Diff View + +The third step of the wizard features a visual diff UI component which is custom to this feature. It is based off Ace/Brace and the custom code used to power is it lives in `lib/diff_ace_addons.js` and `lib/diff_tools.js`. The UI parts are in `sections/wizard/components/review/diff_view.js`. See those individual files for more detailed comments/explanations. + +### Validation + +Every step in the wizard features validation and will show error states after the user attempts to move to the next step assuming there are errors on the current page. + +This works by constantly revalidating the entire wizard state after each state change. This is technically optional as the method to trigger validation is manually called in each UI component that triggers a state change. + +It's important to note that the validation logic does not apply to a single step in the wizard, but will always validate the entire state tree. This helps prevent scenarios where a change in a step might invalidate a change in another step and we lose that validation state. + +Once a step change is initiated (like clicking Next Step), the current step is marked as able to see errors and will reject the change if there are errors. It will show a toast to the user that there are errors and make each error visible on the relevant UI control. + +As a way to consolidate showing these errors, there is a custom UI component called `ErrableFormRow` that wraps a `EuiFormRow` and it's child with the appropriate error states when appropriate. diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js b/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js index 96d3f1cc6849f..82c6e6b4d1e39 100644 --- a/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js +++ b/x-pack/plugins/index_lifecycle_management/public/lib/diff_ace_addons.js @@ -22,6 +22,16 @@ function findInObject(key, obj, debug) { return false; } +/** + * Utilty method that will determine if the current key/value pair + * is an addition or removal and return the appropriate ace classes + * for styling. This is called after finding a valid key/value match + * in our custom JSON diff mode for ace. + * + * @param {string} key + * @param {string} val + * @param {object} jsonObject + */ function getDiffClasses(key, val, jsonObject) { let value = val; if (value.endsWith(',')) { @@ -57,6 +67,14 @@ let currentJsonObject; const getCurrentJsonObject = () => currentJsonObject; export const setCurrentJsonObject = jsonObject => currentJsonObject = jsonObject; +/** + * This function will update the ace editor to support a `DiffJsonMode` that will + * show a merged object (merged through `diff_tools:mergeAndPreserveDuplicateKeys`) + * and highlight additions and removals. The goal of this from a UI perspective is + * to help the user see a visual result of merging two javascript objects. + * + * Read this as a starter: https://github.com/ajaxorg/ace/wiki/Creating-or-Extending-an-Edit-Mode + */ export const addDiffAddonsForAce = () => { const JsonHighlightRules = ace.acequire('ace/mode/json_highlight_rules') .JsonHighlightRules; @@ -72,6 +90,11 @@ export const addDiffAddonsForAce = () => { token: (key, val) => { return getDiffClasses(key, val, getCurrentJsonObject()); }, + // This is designed to match a key:value pair represented in JSON + // like: + // "foo": "bar" + // Be aware when tweaking this that there are idiosyncracies with + // how these work internally in ace. regex: '(?:"([\\w-+]+)"\\s*:\\s*([^\\n\\[]+)$)', }, { diff --git a/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js b/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js index ca2b113c83086..c06835261c759 100644 --- a/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js +++ b/x-pack/plugins/index_lifecycle_management/public/lib/diff_tools.js @@ -6,6 +6,13 @@ export const ADDITION_PREFIX = '$$$'; export const REMOVAL_PREFIX = '^^^'; + +/** + * Utility method that will properly escape the prefixes to use in a valid + * RegExp + * + * @param {string} prefix + */ const escapePrefix = prefix => prefix .split('') @@ -19,6 +26,15 @@ const removePrefixRegex = new RegExp( export const isBoolean = value => JSON.parse(value) === true || JSON.parse(value) === false; const isObject = value => typeof value === 'object' && !Array.isArray(value); + +/** + * Utility method that will determine if the key/value pair provided is different + * than the value found using the key in the provided obj. + * + * @param {object} obj + * @param {string} key + * @param {object} value + */ const isDifferent = (obj, key, value) => { // If the object does not contain the key, then ignore since it's not a removal or addition if (!obj.hasOwnProperty(key)) { @@ -39,6 +55,14 @@ const isDifferent = (obj, key, value) => { // We should be dealing with primitives so do a basic comparison return obj[key] !== value; }; + +/** + * This utility method is called when an object exists in the target object + * but not in the source and we want to mark each part of the object as an + * addition + * + * @param {*} obj + */ const getAdditions = obj => { const result = {}; for (const [key, value] of Object.entries(obj)) { @@ -51,6 +75,12 @@ const getAdditions = obj => { return result; }; +/** + * This method is designed to remove all prefixes from the object previously added + * by `mergeAndPreserveDuplicateKeys` + * + * @param {object} obj + */ export const removePrefixes = obj => { if (typeof obj === 'string') { return obj.replace(removePrefixRegex, ''); @@ -70,6 +100,13 @@ export const removePrefixes = obj => { ); }; +/** + * This function is designed to recursively remove any prefixes added through the + * `mergeAndPreserveDuplicateKeys` process. + * + * @param {string} key + * @param {object} value + */ const normalizeChange = (key, value) => { if (typeof value === 'string') { return { @@ -88,6 +125,17 @@ const normalizeChange = (key, value) => { }, {}); }; +/** + * This function is designed to merge two objects together, but instead of + * overriding key collisions, it will create two keys for each collision - the key + * from the source object will start with the `REMOVAL_PREFIX` and the key from the + * target object will start with the `ADDITION_PREFIX`. The resulting object from + * this function call will contain the merged object and potentially some + * `REMOVAL_PREFIX` and `ADDITION_PREFIX` keys. + * + * @param {object} source + * @param {object} target + */ export const mergeAndPreserveDuplicateKeys = ( source, target, From 475540a65331425ceac688a8c18fe5ca7af1981c Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 11 Jun 2018 15:49:34 -0400 Subject: [PATCH 20/62] Update readme --- x-pack/plugins/index_lifecycle_management/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/index_lifecycle_management/README.md b/x-pack/plugins/index_lifecycle_management/README.md index 304a2f970a6d9..14297875d177c 100644 --- a/x-pack/plugins/index_lifecycle_management/README.md +++ b/x-pack/plugins/index_lifecycle_management/README.md @@ -51,7 +51,9 @@ One example is the `auto_enable_phase.js` middleware. By default, the warm, cold #### Generic phase data -Each of our four phases have some similar and some unique configuration options. Instead of making each individual phase a specific action for that phase, the code is written more generically to capture any data change within a phase to a single action. Therefore, each phase component's configuration inputs will look similar, like: `setPhaseData(PHASE_ROLLOVER_AFTER_UNITS, e.target.value)`. The top level container for each phase will handle automatically prefixing the `setPhaseData` prop with the right phase: ` setPhaseData: (key, value) => setPhaseData(PHASE_COLD, key, value),` +Each of our four phases have some similar and some unique configuration options. Instead of making each individual phase a specific action for that phase, the code is written more generically to capture any data change within a phase to a single action. Therefore, each phase component's configuration inputs will look similar, like: `setPhaseData(PHASE_ROLLOVER_AFTER_UNITS, e.target.value)`. The top level container for each phase will handle automatically prefixing the `setPhaseData` prop with the right phase: ` setPhaseData: (key, value) => setPhaseData(PHASE_COLD, key, value),`. + +To complement this generic logic, there is a list of constants that are used to ensure the right pieces of data are changed. These are contained within `store/constants.js` ### Diff View From 36e001dbe168ad0331d892a069a9c47318cf7b71 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 11 Jun 2018 15:58:23 -0400 Subject: [PATCH 21/62] Do not need this anymore --- x-pack/plugins/index_lifecycle_management/TODO.md | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 x-pack/plugins/index_lifecycle_management/TODO.md diff --git a/x-pack/plugins/index_lifecycle_management/TODO.md b/x-pack/plugins/index_lifecycle_management/TODO.md deleted file mode 100644 index 3d39db9451560..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/TODO.md +++ /dev/null @@ -1,6 +0,0 @@ -- 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 From 934f4fb1b1e57d0c4f4b0f9c326249f20f9b0c6b Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 11 Jun 2018 16:00:43 -0400 Subject: [PATCH 22/62] Remove debug or commented out code --- .../policy_configuration.js | 104 ------------------ .../policy_selection/policy_selection.js | 44 -------- .../wizard/components/review/review.js | 24 ---- .../public/sections/wizard/diff.json | 33 ------ .../public/sections/wizard/wizard.js | 22 ---- 5 files changed, 227 deletions(-) delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json 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 index eacadcba7fd6a..a2ed77bd87f3b 100644 --- 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 @@ -97,27 +97,6 @@ export class PolicyConfiguration extends Component { ); } - // 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 (
@@ -159,89 +138,6 @@ export class PolicyConfiguration extends Component { /> - {/* - - - - {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} - */} - - {/* */} - policy.name === policyName); this.props.setSelectedPolicy(policy); - // this.props.done(); } - render() { const { policies, selectedPolicyName } = this.props; @@ -79,46 +75,6 @@ export class PolicySelection extends Component { - {/* - - - this.selectPolicy(null)} - > - - -

New policy

-
-
-
- {policies.map(item => ( - - this.selectPolicy(item)} - > - -

- {item.name} - {selectedPolicyName === item.name ? '*' : ''} -

-
-
-
- ))} -
- */} - - {/* */} - - {/* - Back - */} ); } 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 87d538ac08b80..4119c6ef1a0ee 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 @@ -8,7 +8,6 @@ import React, { Fragment, Component } from 'react'; import PropTypes from 'prop-types'; import { toastNotifications } from 'ui/notify'; -// import DiffEditor from 'react-ace/lib/diff'; import './review.less'; import 'brace/theme/github'; @@ -111,8 +110,6 @@ export class Review extends Component { const { done, back, - - /* Start might move */ setSelectedPolicyName, setSaveAsNewPolicy, validate, @@ -121,8 +118,6 @@ export class Review extends Component { selectedPolicyName, saveAsNewPolicy, originalPolicyName, - /* End might move */ - selectedIndexTemplateName, affectedIndexTemplates, templateDiff, @@ -139,10 +134,6 @@ export class Review extends Component { return (
- {/* -

Changes that will occur

-
- */}

Review your policy changes

@@ -198,21 +189,6 @@ export class Review extends Component { - {/* */} - ) : null} diff --git a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json deleted file mode 100644 index 9ce2e9b307baa..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/diff.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "originalFullIndexTemplate": { - "settings": { - "index": { - "number_of_shards": "1", - "auto_expand_replicas": "0-1", - "lifecycle": { - "name": "my_policy" - } - } - } - }, - "newFullIndexTemplate": { - "settings": { - "index": { - "number_of_shards": "1", - "auto_expand_replicas": "0-1", - "number_of_replicas": "1", - "lifecycle": { - "name": "my_policy4" - }, - "routing": { - "allocation": { - "include": { - "sattr_name": "node" - } - } - } - } - } - }, - "hasChanged": true -} 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 index 757326c6ed1d2..ab92bc815bd2f 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js @@ -8,7 +8,6 @@ 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 { @@ -25,8 +24,6 @@ import { STRUCTURE_POLICY_CONFIGURATION, STRUCTURE_REVIEW, } from '../../store/constants'; -// import { DiffView } from './components/review/diff_view'; -// import diff from './diff.json'; export class Wizard extends Component { static propTypes = { @@ -100,13 +97,6 @@ export class Wizard extends Component { done={() => this.onSelectedStepChanged(2)} /> ); - // case 2: - // return ( - // this.onSelectedStepChanged(3)} - // back={() => this.onSelectedStepChanged(1)} - // /> - // ); case 2: return ( 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 a policy', isSelected: this.state.selectedStep === 2, @@ -159,8 +142,6 @@ export class Wizard extends Component { }, ]; - // const templateDiff = diff; - return ( @@ -172,9 +153,6 @@ export class Wizard extends Component { - {/* */} {this.renderContent()} From 910f3ebf273597b246c23ab667ebc46c1c6db862 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Tue, 12 Jun 2018 09:34:45 -0400 Subject: [PATCH 23/62] Remove these - they are in the tests PR --- .../indices/__tests__/bootstrap_route.test.js | 56 -------------- .../__tests__/get_affected_route.test.js | 77 ------------------- 2 files changed, 133 deletions(-) delete mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/bootstrap_route.test.js delete mode 100644 x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/get_affected_route.test.js diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/bootstrap_route.test.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/bootstrap_route.test.js deleted file mode 100644 index 5bc48358cd187..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/bootstrap_route.test.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { registerBootstrapRoute } from '../register_bootstrap_route'; - -jest.mock('../../../../lib/call_with_request_factory', () => { - const mock = jest.fn(); - return { - callWithRequestFactory: () => mock, - }; -}); - -jest.mock('../../../../lib/is_es_error_factory', () => ({ - isEsErrorFactory: jest.fn().mockImplementation(() => jest.fn()), -})); - -jest.mock('../../../../lib/license_pre_routing_factory', () => ({ - licensePreRoutingFactory: jest.fn().mockImplementation(() => jest.fn()), -})); - -let routeHandler; -const mockServer = { - route: options => { - routeHandler = options.handler; - } -}; - -describe('ilmBootstrapRoute', () => { - it('should call indices.create', async () => { - registerBootstrapRoute(mockServer); - - await routeHandler({ payload: { - indexName: 'myIndex', - aliasName: 'myAlias', - } }, jest.fn()); - - const mock = require('../../../../lib/call_with_request_factory').callWithRequestFactory().mock; - - expect(mock.calls.length).toBe(1); - expect(mock.calls[0]).toEqual([ - 'indices.create', - { - index: 'myIndex', - aliases: { - myAlias: {} - }, - settings: { - 'index.lifecycle.rollover_alias': 'myAlias' - } - } - ]); - }); -}); diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/get_affected_route.test.js b/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/get_affected_route.test.js deleted file mode 100644 index 67c5865ba1a75..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/indices/__tests__/get_affected_route.test.js +++ /dev/null @@ -1,77 +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 { registerGetAffectedRoute } from '../register_get_affected_route'; - -jest.mock('../../../../lib/call_with_request_factory', () => { - const mock = jest.fn().mockImplementation((method, params) => { - if (params.path === '/_template') { - return { - 'foobar': { - index_patterns: ['foobar*'] - }, - 'barfoo': { - index_patterns: ['barfoo*'], - settings: { - index: { - lifecycle: { - name: 'myPolicy' - } - } - } - } - }; - } - }); - return { - callWithRequestFactory: () => mock, - }; -}); - -jest.mock('../../../../lib/is_es_error_factory', () => ({ - isEsErrorFactory: jest.fn().mockImplementation(() => jest.fn()), -})); - -jest.mock('../../../../lib/license_pre_routing_factory', () => ({ - licensePreRoutingFactory: jest.fn().mockImplementation(() => jest.fn()), -})); - -const routeHandlers = []; -const mockServer = { - route: options => { - routeHandlers.push(options.handler); - } -}; - -describe('ilmGetAffectedRoute', () => { - it('should call indices.create', async () => { - registerGetAffectedRoute(mockServer); - - - for (const routeHandler of routeHandlers) { - await routeHandler({ params: { - indexTemplateName: 'foobar', - policyName: 'myPolicy' - } }, jest.fn()); - } - - const mock = require('../../../../lib/call_with_request_factory').callWithRequestFactory().mock; - - expect(mock.calls.length).toBe(4); - expect(mock.calls[1]).toEqual([ - 'indices.get', - { - index: ['foobar*'] - } - ]); - expect(mock.calls[3]).toEqual([ - 'indices.get', - { - index: ['foobar*', 'barfoo*'] - } - ]); - }); -}); From 99aef825a25573b417495baef590b8602041fb9f Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Fri, 15 Jun 2018 14:08:48 -0400 Subject: [PATCH 24/62] Toggle system indices --- .../template_selection/template_selection.js | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) 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 index 29a1430a4b17b..9614e64414ed5 100644 --- 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, PureComponent } from 'react'; +import React, { Fragment, Component } from 'react'; import PropTypes from 'prop-types'; import { @@ -14,6 +14,7 @@ import { EuiFieldText, EuiDescribedFormGroup, EuiLink, + EuiSpacer, } from '@elastic/eui'; import { ErrableFormRow } from '../../../../form_errors'; @@ -23,7 +24,7 @@ import { STRUCTURE_ALIAS_NAME, } from '../../../../../../store/constants'; -export class TemplateSelection extends PureComponent { +export class TemplateSelection extends Component { static propTypes = { fetchIndexTemplates: PropTypes.func.isRequired, setSelectedIndexTemplate: PropTypes.func.isRequired, @@ -35,10 +36,21 @@ export class TemplateSelection extends PureComponent { 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, @@ -48,7 +60,6 @@ export class TemplateSelection extends PureComponent { setAliasName, bootstrapEnabled, - templateOptions, selectedIndexTemplateIndices, indexName, aliasName, @@ -57,6 +68,15 @@ export class TemplateSelection extends PureComponent { 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 a template} @@ -72,6 +92,12 @@ export class TemplateSelection extends PureComponent {

} > + + Date: Mon, 18 Jun 2018 15:59:00 -0400 Subject: [PATCH 25/62] Aliases are not defined here anymore --- .../public/store/selectors/policies.js | 5 +---- 1 file changed, 1 insertion(+), 4 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 94439f27c72a2..805a0818f0b61 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 @@ -31,7 +31,6 @@ import { PHASE_PRIMARY_SHARD_COUNT, PHASE_REPLICA_COUNT, PHASE_ENABLED, - PHASE_ROLLOVER_ALIAS, PHASE_ATTRIBUTES_THAT_ARE_NUMBERS, MAX_SIZE_TYPE_DOCUMENT } from '../constants'; @@ -182,9 +181,7 @@ export const phaseToES = (state, phase) => { esPhase.actions = {}; if (phase[PHASE_ROLLOVER_ENABLED]) { - esPhase.actions.rollover = { - alias: phase[PHASE_ROLLOVER_ALIAS], - }; + esPhase.actions.rollover = {}; if (isNumber(phase[PHASE_ROLLOVER_MAX_AGE])) { esPhase.actions.rollover.max_age = `${phase[PHASE_ROLLOVER_MAX_AGE]}${ From db39544bb848f7815d842453693143eedbae5fc1 Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Mon, 18 Jun 2018 16:42:48 -0400 Subject: [PATCH 26/62] Handle rollover better in warm phase and remove from cold,delete --- .../components/cold_phase/cold_phase.js | 2 -- .../components/delete_phase/delete_phase.js | 2 -- .../components/warm_phase/warm_phase.js | 17 ++++---------- .../public/store/selectors/policies.js | 23 +++++++++++-------- 4 files changed, 19 insertions(+), 25 deletions(-) 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 index 7a0da69affcb6..dc55d36b4d067 100644 --- 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 @@ -23,7 +23,6 @@ import { } from '@elastic/eui'; import { PHASE_ENABLED, - PHASE_ROLLOVER_ENABLED, PHASE_ROLLOVER_ALIAS, PHASE_ROLLOVER_AFTER, PHASE_ROLLOVER_AFTER_UNITS, @@ -42,7 +41,6 @@ export class ColdPhase extends PureComponent { 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, 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 index 7c674116c0fa6..8d9e179dc99fa 100644 --- 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 @@ -26,7 +26,6 @@ import { } from '@elastic/eui'; import { PHASE_ENABLED, - PHASE_ROLLOVER_ENABLED, PHASE_ROLLOVER_AFTER, PHASE_ROLLOVER_AFTER_UNITS, } from '../../../../../../store/constants'; @@ -41,7 +40,6 @@ export class DeletePhase extends PureComponent { 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 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 index 5af74cf85e57f..a31f58ec30352 100644 --- 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 @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { Fragment, Component } from 'react'; +import React, { Fragment, PureComponent } from 'react'; import PropTypes from 'prop-types'; import { @@ -39,7 +39,7 @@ import { } from '../../../../../../store/constants'; import { ErrableFormRow } from '../../../../form_errors'; -export class WarmPhase extends Component { +export class WarmPhase extends PureComponent { static propTypes = { setPhaseData: PropTypes.func.isRequired, validate: PropTypes.func.isRequired, @@ -84,13 +84,6 @@ export class WarmPhase extends Component { nodeOptions: PropTypes.array.isRequired, }; - constructor(props) { - super(props); - this.state = { - applyOnRollover: false, - }; - } - componentWillMount() { this.props.fetchNodes(); } @@ -160,15 +153,15 @@ export class WarmPhase extends Component { { - await this.setState({ applyOnRollover: e.target.checked }); + await setPhaseData(PHASE_ROLLOVER_ENABLED, e.target.checked); validate(); }} /> ) : null} - {!this.state.applyOnRollover ? ( + {!phaseData[PHASE_ROLLOVER_ENABLED] ? ( { export const isNumber = value => typeof value === 'number'; -export const phaseFromES = (phase, defaultPolicy) => { +export const phaseFromES = (phase, phaseName, defaultPolicy) => { const policy = { ...defaultPolicy }; if (!phase) { @@ -91,13 +91,20 @@ export const phaseFromES = (phase, defaultPolicy) => { } policy[PHASE_ENABLED] = true; + policy[PHASE_ROLLOVER_ENABLED] = false; if (phase.after) { const { size: after, units: afterUnits } = splitSizeAndUnits( phase.after ); - policy[PHASE_ROLLOVER_AFTER] = after; - policy[PHASE_ROLLOVER_AFTER_UNITS] = afterUnits; + // If the after is set to 0s, it effectively means we are moving + // to the warm phase after rollover from the hot phase + if (phaseName === PHASE_WARM && after === 0) { + policy[PHASE_ROLLOVER_ENABLED] = true; + } else { + policy[PHASE_ROLLOVER_AFTER] = after; + policy[PHASE_ROLLOVER_AFTER_UNITS] = afterUnits; + } } if (phase.actions) { @@ -124,8 +131,6 @@ export const phaseFromES = (phase, defaultPolicy) => { 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) { @@ -159,10 +164,10 @@ export const policyFromES = ({ name, type, phases }) => { 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) + [PHASE_HOT]: phaseFromES(phases[PHASE_HOT], PHASE_HOT, defaultHotPhase), + [PHASE_WARM]: phaseFromES(phases[PHASE_WARM], PHASE_WARM, defaultWarmPhase), + [PHASE_COLD]: phaseFromES(phases[PHASE_COLD], PHASE_COLD, defaultColdPhase), + [PHASE_DELETE]: phaseFromES(phases[PHASE_DELETE], PHASE_DELETE, defaultDeletePhase) } }; }; From ec2dc4e49efc23a24208516ef458865f175cef01 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Wed, 1 Aug 2018 11:02:50 -0400 Subject: [PATCH 27/62] adding learn more link component and switching over to using that --- .../public/components/learn_more_link.js | 30 +++++++++++++++++++ .../components/configuration/configuration.js | 8 ++--- .../template_selection/template_selection.js | 8 ++--- .../components/hot_phase/hot_phase.js | 8 ++--- .../components/warm_phase/warm_phase.js | 13 ++++---- 5 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 x-pack/plugins/index_lifecycle_management/public/components/learn_more_link.js 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 new file mode 100644 index 0000000000000..17f6e5e2d1661 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/components/learn_more_link.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 React from 'react'; +import { EuiLink } from '@elastic/eui'; +import { ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } from 'ui/documentation_links'; + +const esBase = `${ELASTIC_WEBSITE_URL}guide/en/elasticsearch/reference/${DOC_LINK_VERSION}/`; + + +export class LearnMoreLink extends React.PureComponent { + render() { + const { href, docPath } = this.props; + let url; + if (docPath) { + url = `${esBase}${docPath}`; + } else { + url = href; + } + return ( + + Learn more + + ); + + } +} \ No newline at end of file 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 index 707bf4d9dcad2..b107cfae9043b 100644 --- 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 @@ -15,9 +15,9 @@ import { EuiFieldNumber, EuiCallOut, EuiButtonEmpty, - EuiLink, EuiDescribedFormGroup, } from '@elastic/eui'; +import { LearnMoreLink } from '../../../../../../components/learn_more_link'; import { STRUCTURE_NODE_ATTRS, STRUCTURE_PRIMARY_NODES, @@ -130,9 +130,9 @@ export class Configuration extends Component {

The best way to determine how many shards you need is to benchmark using realistic data and queries on your hardware.{' '} - - Learn more - +

} /> 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 index 9614e64414ed5..ccfc199a83540 100644 --- 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 @@ -13,10 +13,10 @@ import { EuiSwitch, EuiFieldText, EuiDescribedFormGroup, - EuiLink, EuiSpacer, } from '@elastic/eui'; +import { LearnMoreLink } from '../../../../../../components/learn_more_link'; import { ErrableFormRow } from '../../../../form_errors'; import { STRUCTURE_TEMPLATE_NAME, @@ -86,9 +86,9 @@ export class TemplateSelection extends Component {

An index template defines the settings, mappings, and aliases to apply when you create an index.{' '} - - Learn more - +

} > 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 index 2510e264f9395..04ba438f9b671 100644 --- 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 @@ -16,11 +16,11 @@ import { EuiFieldNumber, EuiSelect, EuiSwitch, - EuiLink, EuiFormRow, EuiDescribedFormGroup, EuiBetaBadge, } from '@elastic/eui'; +import { LearnMoreLink } from '../../../../../../components/learn_more_link'; import { PHASE_ROLLOVER_ALIAS, PHASE_ROLLOVER_MAX_AGE, @@ -96,9 +96,9 @@ export class HotPhase extends PureComponent { helpText={

If true, rollover the index when it gets too big or too old. The alias switches to the new index.{' '} - - Learn more - +

} > 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 index a31f58ec30352..bd46a44907b83 100644 --- 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 @@ -6,7 +6,6 @@ import React, { Fragment, PureComponent } from 'react'; import PropTypes from 'prop-types'; - import { EuiFlexGroup, EuiFlexItem, @@ -19,7 +18,6 @@ import { EuiSelect, EuiSwitch, EuiButtonEmpty, - EuiLink, EuiDescribedFormGroup, EuiBetaBadge, EuiButton, @@ -38,6 +36,7 @@ import { 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 = { @@ -273,9 +272,9 @@ export class WarmPhase extends PureComponent { Shrink the index into a new index with fewer primary shards.{' '} - - Learn more - + @@ -343,9 +342,7 @@ export class WarmPhase extends PureComponent { Reduce the number of segments in your shard by merging smaller files and clearing deleted ones.{' '} - - Learn more - +
From 77f65e490b3c25674699ba622634847f80f01e69 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Wed, 1 Aug 2018 13:46:01 -0400 Subject: [PATCH 28/62] fixing UI issue when no policies exist --- .../server/routes/api/policies/register_fetch_route.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 6ec6745e80b21..0471dbc717bcd 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 @@ -10,6 +10,9 @@ import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory'; function formatHits(hits) { + if (hits.status === 404) { + return []; + } return Object.keys(hits).reduce((accum, lifecycleName) => { const hit = hits[lifecycleName]; accum.push({ @@ -24,7 +27,7 @@ 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 + // we allow 404 since they may have no policies ignore: [ 404 ] }; From bc52ab19923df2b7a0796b7270ac046c705df647 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Fri, 3 Aug 2018 08:14:19 -0400 Subject: [PATCH 29/62] various fixes --- .../public/api/index.js | 3 + .../components/configuration/configuration.js | 4 +- .../template_selection/template_selection.js | 2 +- .../components/cold_phase/cold_phase.js | 4 +- .../components/delete_phase/delete_phase.js | 1 + .../components/hot_phase/hot_phase.js | 2 + .../components/warm_phase/warm_phase.js | 15 +++-- .../policy_selection/policy_selection.js | 55 ++++++++++--------- .../public/store/constants.js | 1 + .../public/store/reducers/nodes.js | 13 ++++- .../public/store/reducers/policies.js | 8 +-- .../public/store/selectors/index_template.js | 14 +++-- .../public/store/selectors/nodes.js | 2 +- .../indices/register_get_affected_route.js | 17 +++--- .../api/lifecycle/register_create_route.js | 2 +- .../api/policies/register_fetch_route.js | 2 +- .../api/templates/register_fetch_route.js | 1 + 17 files changed, 88 insertions(+), 58 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 c771697e6b27a..a67e3c22ae48b 100644 --- a/x-pack/plugins/index_lifecycle_management/public/api/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/api/index.js @@ -27,6 +27,9 @@ export async function loadIndexTemplates() { } export async function loadIndexTemplate(templateName) { + if (!templateName) { + return {}; + } const response = await httpClient.get(`${apiPrefix}/template/${templateName}`); return response.data; } 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 index b107cfae9043b..76ee426662587 100644 --- 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 @@ -115,7 +115,7 @@ export class Configuration extends Component { ) : null} > { await setSelectedNodeAttrs(e.target.value); validate(); @@ -151,6 +151,7 @@ export class Configuration extends Component { validate(); }} value={selectedPrimaryShardCount} + min={1} /> @@ -167,6 +168,7 @@ export class Configuration extends Component { validate(); }} value={selectedReplicaCount} + min={0} /> 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 index ccfc199a83540..eaf13bb9a4afa 100644 --- 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 @@ -105,7 +105,7 @@ export class TemplateSelection extends Component { errors={errors} > { await setSelectedIndexTemplate(e.target.value); validate(); 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 index dc55d36b4d067..a983f4f101335 100644 --- 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 @@ -133,6 +133,7 @@ export class ColdPhase extends PureComponent { setPhaseData(PHASE_ROLLOVER_AFTER, e.target.value); validate(); }} + min={1} /> @@ -170,7 +171,7 @@ export class ColdPhase extends PureComponent { ) : null} > { await setPhaseData(PHASE_NODE_ATTRS, e.target.value); @@ -193,6 +194,7 @@ export class ColdPhase extends PureComponent { await setPhaseData(PHASE_REPLICA_COUNT, e.target.value); validate(); }} + min={0} /> 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 index 8d9e179dc99fa..ae1926a714837 100644 --- 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 @@ -119,6 +119,7 @@ export class DeletePhase extends PureComponent { setPhaseData(PHASE_ROLLOVER_AFTER, e.target.value); validate(); }} + min={1} /> 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 index 04ba438f9b671..1ee81eff53a03 100644 --- 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 @@ -131,6 +131,7 @@ export class HotPhase extends PureComponent { ); validate(); }} + min={1} /> @@ -173,6 +174,7 @@ export class HotPhase extends PureComponent { await setPhaseData(PHASE_ROLLOVER_MAX_AGE, e.target.value); validate(); }} + min={1} /> 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 index bd46a44907b83..265d3999bc020 100644 --- 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 @@ -24,7 +24,7 @@ import { } from '@elastic/eui'; import { PHASE_ENABLED, - PHASE_ROLLOVER_ENABLED, + WARM_PHASE_ON_ROLLOVER, PHASE_ROLLOVER_ALIAS, PHASE_FORCE_MERGE_ENABLED, PHASE_FORCE_MERGE_SEGMENTS, @@ -48,7 +48,7 @@ export class WarmPhase extends PureComponent { errors: PropTypes.object.isRequired, phaseData: PropTypes.shape({ [PHASE_ENABLED]: PropTypes.bool.isRequired, - [PHASE_ROLLOVER_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([ @@ -152,15 +152,15 @@ export class WarmPhase extends PureComponent { { - await setPhaseData(PHASE_ROLLOVER_ENABLED, e.target.checked); + await setPhaseData(WARM_PHASE_ON_ROLLOVER, e.target.checked); validate(); }} /> ) : null} - {!phaseData[PHASE_ROLLOVER_ENABLED] ? ( + {!phaseData[WARM_PHASE_ON_ROLLOVER] ? ( @@ -220,7 +221,7 @@ export class WarmPhase extends PureComponent { } > { await setPhaseData(PHASE_NODE_ATTRS, e.target.value); @@ -310,6 +311,7 @@ export class WarmPhase extends PureComponent { ); validate(); }} + min={1} /> @@ -375,6 +377,7 @@ export class WarmPhase extends PureComponent { ); validate(); }} + min={1} /> ) : null} 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 index 97ab62ddb4c82..3939ccf8424f7 100644 --- 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 @@ -22,7 +22,7 @@ export class PolicySelection extends Component { setSelectedPolicy: PropTypes.func.isRequired, selectedPolicyName: PropTypes.string.isRequired, - policies: PropTypes.array.isRequired + policies: PropTypes.array.isRequired, }; componentWillMount() { @@ -36,42 +36,43 @@ export class PolicySelection extends Component { render() { const { policies, selectedPolicyName } = this.props; - - const options = policies.map(item => ({ value: item.name, text: item.name })); - options.unshift({ - value: '', - text: '-- New Policy --' - }); + let existingPoliciesSelect; + const policiesExist = policies.length > 0; + if (policiesExist) { + const options = policies.map(item => ({ value: item.name, text: item.name })); + options.unshift({ + value: '', + text: '-- New Policy --', + }); + existingPoliciesSelect = ( + + + { + await this.selectPolicy(e.target.value); + }} + /> + + + ); + } return ( Select or create a policy} + title={

{policiesExist ? 'Select or c' : 'C'}reate a policy

} titleSize="s" - description="An index lifecycle policy is a + description={`An index lifecycle policy is a blueprint for transitioning your data over time. - You can create a new policy or edit an existing - policy and save it with a new name." + You can create a new policy${policiesExist ? ' or edit an existing policy and save it with a new name.' : '.'}`} fullWidth > - - - { - await this.selectPolicy(e.target.value); - }} - /> - - + {existingPoliciesSelect} - this.selectPolicy()} - > - Create new policy - + this.selectPolicy()}>Create new policy 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 04c59709bd426..3373946740d01 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/constants.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/constants.js @@ -17,6 +17,7 @@ export const PHASE_ENABLED = 'phaseEnabled'; export const MAX_SIZE_TYPE_DOCUMENT = 'd'; export const PHASE_ROLLOVER_ENABLED = 'rolloverEnabled'; +export const WARM_PHASE_ON_ROLLOVER = 'warmPhaseOnRollover'; export const PHASE_ROLLOVER_ALIAS = 'selectedAlias'; export const PHASE_ROLLOVER_MAX_AGE = 'selectedMaxAge'; export const PHASE_ROLLOVER_MAX_AGE_UNITS = 'selectedMaxAgeUnits'; 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 index a5a372ed17a8a..5e8e01eab26df 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/reducers/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/reducers/nodes.js @@ -58,11 +58,18 @@ export const nodes = handleActions( }; }, [setSelectedReplicaCount](state, { payload }) { - let selectedReplicaCount = parseInt(payload); - if (isNaN(selectedReplicaCount)) { - selectedReplicaCount = ''; + let selectedReplicaCount; + if (payload != null) { + selectedReplicaCount = parseInt(payload); + if (isNaN(selectedReplicaCount)) { + selectedReplicaCount = ''; + } + } else { + // default value for Elasticsearch + selectedReplicaCount = 1; } + return { ...state, selectedReplicaCount 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 982b20381dc50..0c147b7d14222 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 @@ -37,12 +37,12 @@ import { PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS, PHASE_ROLLOVER_ALIAS, PHASE_ROLLOVER_MAX_DOC_SIZE, - PHASE_SHRINK_ENABLED + PHASE_SHRINK_ENABLED, + WARM_PHASE_ON_ROLLOVER } from '../constants'; export const defaultWarmPhase = { [PHASE_ENABLED]: false, - [PHASE_ROLLOVER_ENABLED]: false, [PHASE_ROLLOVER_ALIAS]: '', [PHASE_FORCE_MERGE_SEGMENTS]: '', [PHASE_FORCE_MERGE_ENABLED]: false, @@ -51,7 +51,8 @@ export const defaultWarmPhase = { [PHASE_NODE_ATTRS]: '', [PHASE_SHRINK_ENABLED]: true, [PHASE_PRIMARY_SHARD_COUNT]: '', - [PHASE_REPLICA_COUNT]: '' + [PHASE_REPLICA_COUNT]: '', + [WARM_PHASE_ON_ROLLOVER]: false }; export const defaultHotPhase = { @@ -67,7 +68,6 @@ export const defaultHotPhase = { export const defaultColdPhase = { [PHASE_ENABLED]: false, - [PHASE_ROLLOVER_ENABLED]: false, [PHASE_ROLLOVER_ALIAS]: '', [PHASE_ROLLOVER_AFTER]: '', [PHASE_ROLLOVER_AFTER_UNITS]: 's', 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 9992c7491d368..06786a385b774 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 @@ -58,9 +58,13 @@ export const getSelectedIndexTemplate = createSelector( export const getFullSelectedIndexTemplate = state => state.indexTemplate.fullSelectedIndexTemplate; export const getAlias = state => { - const template = getSelectedIndexTemplate(state); - if (template && template.settings) { - return template.settings.indexlifecycle.rollover_alias; + const indexTemplate = getSelectedIndexTemplate(state); + if (!indexTemplate) { + return undefined; + } + const { settings = {} } = indexTemplate; + if (settings.indexlifecycle) { + return settings.indexlifecycle.rollover_alias; } return undefined; }; @@ -126,8 +130,8 @@ export const getTemplateDiff = state => { const newFullIndexTemplate = merge(cloneDeep(originalFullIndexTemplate), { settings: { index: { - number_of_shards: '' + getSelectedPrimaryShardCount(state), - number_of_replicas: '' + getSelectedReplicaCount(state), + number_of_shards: getSelectedPrimaryShardCount(state), + number_of_replicas: getSelectedReplicaCount(state), lifecycle: { name: getSelectedPolicyName(state) }, 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 index 4a65cf969bdb5..b92f96422e6b6 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/nodes.js @@ -32,7 +32,7 @@ export const getNodeOptions = createSelector( export const getSelectedPrimaryShardCount = state => state.nodes.selectedPrimaryShardCount; export const getSelectedReplicaCount = state => - state.nodes.selectedReplicaCount; + state.nodes.selectedReplicaCount !== undefined ? state.nodes.selectedReplicaCount : 1; export const getSelectedNodeAttrs = state => state.nodes.selectedNodeAttrs; export const getNodesFromSelectedNodeAttrs = state => { const nodes = getNodes(state)[getSelectedNodeAttrs(state)]; 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 fc7f5f2d2d131..e26d04600f15e 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 @@ -13,7 +13,7 @@ async function fetchTemplates(callWithRequest) { const params = { method: 'GET', path: '/_template', - // we allow 404 incase the user shutdown security in-between the check and now + // we allow 404 in case there are no templates ignore: [404] }; @@ -27,7 +27,7 @@ async function getAffectedIndices( ) { const templates = await fetchTemplates(callWithRequest); - if (!templates || Object.keys(templates).length === 0) { + if (!templates || Object.keys(templates).length === 0 | templates.status === 404) { return []; } @@ -48,12 +48,15 @@ async function getAffectedIndices( if (!indexPatterns || indexPatterns.length === 0) { return []; } + const indexParams = { + method: 'GET', + path: `/${indexPatterns.join(',')}`, + // we allow 404 in case there are no indices + ignore: [404] + }; + const indices = await callWithRequest('transport.request', indexParams); - const indices = await callWithRequest('indices.get', { - index: indexPatterns - }); - - if (!indices) { + if (!indices || indices.status === 404) { return []; } 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 84e2637ab5a4c..cc7822e28da68 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 @@ -21,7 +21,7 @@ async function createLifecycle(callWithRequest, lifecycle) { }; const params = { method: 'PUT', - path: `/_xpack/index_lifecycle/${lifecycle.name}`, + path: `/_ilm/${lifecycle.name}`, ignore: [ 404 ], body, }; 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 0471dbc717bcd..75e88426f65f8 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 formatHits(hits) { async function fetchPolicies(callWithRequest) { const params = { method: 'GET', - path: '/_xpack/index_lifecycle', + path: '/_ilm', // we allow 404 since they may have no policies ignore: [ 404 ] }; 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 7bc4922478be0..a8aaf38868e7a 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 @@ -21,6 +21,7 @@ async function formatTemplates(templates, callWithRequest) { index_lifecycle_name: settings.index && settings.index.lifecycle ? settings.index.lifecycle.name : undefined, index_patterns, allocation_rules: settings.index && settings.index.routing ? settings.index.routing : undefined, + settings, name: templateName, }; From e19215334ea2c8cbed97c2da3dd875e20fba1c04 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Thu, 9 Aug 2018 12:30:43 -0400 Subject: [PATCH 30/62] some cleanup --- .../index_lifecycle_management/public/app.js | 7 +- .../public/sections/landing/index.js | 10 --- .../sections/landing/landing.container.js | 24 ------- .../public/sections/landing/landing.js | 43 ------------ .../sections/wizard/wizard.container.js | 6 +- .../public/sections/wizard/wizard.js | 68 +++++++++++-------- 6 files changed, 45 insertions(+), 113 deletions(-) delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/landing/index.js delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/landing/landing.container.js delete mode 100644 x-pack/plugins/index_lifecycle_management/public/sections/landing/landing.js diff --git a/x-pack/plugins/index_lifecycle_management/public/app.js b/x-pack/plugins/index_lifecycle_management/public/app.js index 2f5c19a16b684..78561b785f28c 100644 --- a/x-pack/plugins/index_lifecycle_management/public/app.js +++ b/x-pack/plugins/index_lifecycle_management/public/app.js @@ -4,12 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ - - - import React from 'react'; -import { Landing } from './sections/landing'; +import { Wizard } from './sections/wizard'; export const App = () => ( - + ); 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 deleted file mode 100644 index cc858ed0f20e5..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/sections/landing/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 { 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 deleted file mode 100644 index 93e507b00ab7b..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/sections/landing/landing.container.js +++ /dev/null @@ -1,24 +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 { 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 deleted file mode 100644 index c9b2366e97e05..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/sections/landing/landing.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - - - - -import 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/wizard.container.js b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.container.js index 2b76624165a78..84c94f2c82387 100644 --- 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 @@ -10,8 +10,10 @@ import { connect } from 'react-redux'; import '../../less/main.less'; import { Wizard as PresentationComponent } from './wizard'; -import { saveLifecycle } from '../../store/actions'; +import { saveLifecycle, fetchIndexTemplates } from '../../store/actions'; + import { + getIndexTemplates, getIndexTemplatePatch, getBootstrapEnabled, getIndexName, @@ -26,8 +28,10 @@ export const Wizard = connect( 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 index ab92bc815bd2f..ed579e0e4aca0 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js @@ -25,6 +25,9 @@ import { 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, @@ -34,17 +37,21 @@ export class Wizard extends Component { 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: 1, + selectedStep: STEP_INDEX_TEMPLATE, errors: this.getErrors(), }; } - + componentDidMount() { + this.props.fetchIndexTemplates(); + } onSelectedStepChanged = selectedStep => { this.setState({ selectedStep, @@ -89,57 +96,58 @@ export class Wizard extends Component { const { selectedStep, errors } = this.state; switch (selectedStep) { - case 1: + case STEP_INDEX_TEMPLATE: return ( this.onSelectedStepChanged(2)} + done={() => this.onSelectedStepChanged(selectedStep + 1)} /> ); - case 2: + case STEP_POLICY_CONFIGURATION: return ( this.onSelectedStepChanged(3)} - back={() => this.onSelectedStepChanged(1)} + done={() => this.onSelectedStepChanged(selectedStep + 1)} + back={() => this.onSelectedStepChanged(selectedStep - 1)} /> ); - case 3: + case STEP_REVIEW: return ( this.onSelectedStepChanged(2)} + back={() => 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 = [ - { - title: 'Select a template', - isSelected: this.state.selectedStep === 1, - isComplete: this.state.selectedStep > 1, - onClick: () => this.onSelectedStepChanged(1), - }, - { - title: 'Configure a policy', - isSelected: this.state.selectedStep === 2, - isComplete: this.state.selectedStep > 2, - disabled: this.state.selectedStep < 2, - onClick: () => this.onSelectedStepChanged(2), - }, - { - title: 'Review and save', - isSelected: this.state.selectedStep === 3, - isComplete: this.state.selectedStep > 3, - disabled: this.state.selectedStep < 3, - onClick: () => this.onSelectedStepChanged(3), - }, + this.createStep('Select a template', STEP_INDEX_TEMPLATE), + this.createStep('Configure a policy', STEP_POLICY_CONFIGURATION), + this.createStep('Review and save', STEP_REVIEW), ]; return ( From eca34f9eb59add0769883bfb4bf2cb06df2fccd3 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Mon, 13 Aug 2018 08:58:04 -0400 Subject: [PATCH 31/62] moving number_of_replicas due to API change --- .../public/store/selectors/policies.js | 10 +++------- 1 file changed, 3 insertions(+), 7 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 cf2f859fffbca..d01304d29e5dd 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 @@ -211,6 +211,9 @@ export const phaseToES = (state, phase) => { _name: phase[PHASE_NODE_ATTRS] } }; + if (isNumber(phase[PHASE_REPLICA_COUNT])) { + esPhase.actions.allocate.number_of_replicas = phase[PHASE_REPLICA_COUNT]; + } } if (phase[PHASE_FORCE_MERGE_ENABLED]) { @@ -224,12 +227,5 @@ export const phaseToES = (state, phase) => { 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; }; From bc52b195ee052be584b221d93a8a1257ea67d8b3 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Wed, 15 Aug 2018 09:39:34 -0400 Subject: [PATCH 32/62] modifying some messaging --- .../components/configuration/configuration.js | 47 ++++++++----------- .../public/store/selectors/nodes.js | 5 -- 2 files changed, 19 insertions(+), 33 deletions(-) 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 index 76ee426662587..ac4d153b08f15 100644 --- 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 @@ -35,20 +35,13 @@ export class Configuration extends Component { setSelectedReplicaCount: PropTypes.func.isRequired, validate: PropTypes.func.isRequired, - selectedPrimaryShardCount: PropTypes.oneOfType([ - PropTypes.number, - PropTypes.string, - ]).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, + selectedReplicaCount: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, isShowingErrors: PropTypes.bool.isRequired, errors: PropTypes.object.isRequired, - isPrimaryShardCountHigherThanSelectedNodeAttrsCount: - PropTypes.bool.isRequired, + isPrimaryShardCountHigherThanSelectedNodeAttrsCount: PropTypes.bool.isRequired, }; constructor(props) { @@ -98,21 +91,21 @@ export class Configuration extends Component { fullWidth > - this.setState({ isShowingNodeDetailsFlyout: true }) - } - > - View a list of nodes attached to this configuration - - ) : null} + helpText={ + selectedNodeAttrs ? ( + this.setState({ isShowingNodeDetailsFlyout: true })} + > + View a list of nodes attached to this configuration + + ) : null + } > - The best way to determine how many shards you need is to benchmark - using realistic data and queries on your hardware.{' '} - + The best way to determine how many shards you need is to benchmark using realistic + data and queries on your hardware.{' '} +

} /> 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 index b92f96422e6b6..887dddc2d3c00 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/selectors/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/selectors/nodes.js @@ -20,11 +20,6 @@ export const getNodeOptions = createSelector( })); options.sort((a, b) => a.value.localeCompare(b.value)); - options.unshift({ - text: '-- Do not reallocate my indices --', - value: undefined, - }); - return options; } ); From 472213bbdae9d90c9d05716e25e84cf62ffe87fe Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Mon, 20 Aug 2018 10:11:28 -0400 Subject: [PATCH 33/62] fixing typo --- .../components/delete_phase/delete_phase.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index ae1926a714837..52226029b1111 100644 --- 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 @@ -96,7 +96,7 @@ export class DeletePhase extends PureComponent { validate(); }} > - Deactive cold phase + Deactive delete phase
From e3ba85fa6f5dd3dc251d03a7457cc8dabe9697aa Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Mon, 20 Aug 2018 11:59:48 -0400 Subject: [PATCH 34/62] fixing some diff issues and not adding sattr_name if none chosen --- .../public/store/selectors/index_template.js | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 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 06786a385b774..29524aad9863d 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 @@ -127,24 +127,28 @@ export const getExistingAllocationRules = state => { const hasJSONChanged = (json1, json2) => JSON.stringify(json1) !== JSON.stringify(json2); export const getTemplateDiff = state => { const originalFullIndexTemplate = getFullSelectedIndexTemplate(state) || { settings: {} }; - const newFullIndexTemplate = merge(cloneDeep(originalFullIndexTemplate), { + const attributeName = getSelectedNodeAttrs(state); + const baseNewFullIndexTemplate = { settings: { index: { - number_of_shards: getSelectedPrimaryShardCount(state), - number_of_replicas: getSelectedReplicaCount(state), + number_of_shards: getSelectedPrimaryShardCount(state) + '', + number_of_replicas: getSelectedReplicaCount(state) + '', lifecycle: { name: getSelectedPolicyName(state) }, - routing: { - allocation: { - include: { - sattr_name: getSelectedNodeAttrs(state), - } - } - } } } - }); + }; + if (attributeName) { + baseNewFullIndexTemplate.routing = { + allocation: { + include: { + sattr_name: attributeName, + } + } + }; + } + const newFullIndexTemplate = merge(cloneDeep(originalFullIndexTemplate), baseNewFullIndexTemplate); return { originalFullIndexTemplate, From e97639e3a87d2e979d57a5bf5e3c18a6a3a64363 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Wed, 22 Aug 2018 11:18:01 -0400 Subject: [PATCH 35/62] making write alias required for template step and making necessary API changes --- .../template_selection/template_selection.js | 30 +++++++++---------- .../public/store/selectors/index_template.js | 7 ++++- .../public/store/selectors/lifecycle.js | 4 +-- .../api/indices/register_bootstrap_route.js | 8 +---- .../api/lifecycle/register_create_route.js | 4 +++ 5 files changed, 28 insertions(+), 25 deletions(-) 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 index eaf13bb9a4afa..4f8acc5f7b6e5 100644 --- 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 @@ -113,6 +113,20 @@ export class TemplateSelection extends Component { options={templateOptions} /> + + { + await setAliasName(e.target.value); + validate(); + }} + /> + {selectedIndexTemplateName && selectedIndexTemplateIndices.length === 0 ? ( @@ -120,7 +134,7 @@ export class TemplateSelection extends Component { style={{ maxWidth: '100%' }} checked={bootstrapEnabled} onChange={e => setBootstrapEnabled(e.target.checked)} - label={Create an index and alias for this template} + label={Create an index for this template} /> {bootstrapEnabled ? ( @@ -139,20 +153,6 @@ export class TemplateSelection extends Component { }} /> - - { - await setAliasName(e.target.value); - validate(); - }} - /> - ) : null} 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 29524aad9863d..d470b6474660b 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 @@ -17,6 +17,7 @@ import { getSelectedReplicaCount, getSelectedNodeAttrs } from '.'; +import { getAliasName } from './general'; export const getIndexTemplates = state => state.indexTemplate.indexTemplates; export const getIndexTemplateOptions = createSelector( @@ -49,6 +50,9 @@ export const getSelectedIndexTemplate = createSelector( state => getIndexTemplates(state) ], (selectedIndexTemplateName, allTemplates) => { + if (!allTemplates) { + return null; + } return allTemplates.find( template => template.name === selectedIndexTemplateName ); @@ -174,6 +178,7 @@ export const getIndexTemplatePatch = state => { primaryShardCount: getSelectedPrimaryShardCount(state), replicaCount: getSelectedReplicaCount(state), lifecycleName: getSelectedPolicyName(state), - nodeAttrs: getSelectedNodeAttrs(state) + nodeAttrs: getSelectedNodeAttrs(state), + rolloverAlias: getAliasName(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 index 49a074fc4b90a..fcbdb66909fc9 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 @@ -121,8 +121,8 @@ export const validateLifecycle = state => { errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][STRUCTURE_INDEX_NAME].push('An index name is required'); } - if (getBootstrapEnabled(state) && !getAliasName(state)) { - errors[STRUCTURE_INDEX_TEMPLATE][STRUCTURE_TEMPLATE_SELECTION][STRUCTURE_ALIAS_NAME].push('An alias 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))) { 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 ad7128903b99c..22902c925ccfa 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 @@ -11,13 +11,7 @@ import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_facto async function bootstrap(callWithRequest, payload) { await callWithRequest('indices.create', { - index: payload.indexName, - aliases: { - [payload.aliasName]: {} - }, - settings: { - 'index.lifecycle.rollover_alias': payload.aliasName, - } + index: payload.indexName }); } 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 cc7822e28da68..16ef4cd1451f0 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 @@ -38,12 +38,16 @@ async function updateIndexTemplate(callWithRequest, indexTemplatePatch) { // Fetch existing template const template = await getIndexTemplate(callWithRequest, indexTemplatePatch.indexTemplate); merge(template, { + aliases: { + [indexTemplatePatch.rolloverAlias]: {} + }, settings: { index: { number_of_shards: indexTemplatePatch.primaryShardCount, number_of_replicas: indexTemplatePatch.replicaCount, lifecycle: { name: indexTemplatePatch.lifecycleName, + rollover_alias: indexTemplatePatch.rolloverAlias }, routing: { allocation: { From 61a3f953f002fea0d201bf9ec89481ce2c2a3ea2 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Wed, 22 Aug 2018 14:12:04 -0400 Subject: [PATCH 36/62] removing alias definition from template patching as it needs to be per index --- .../routes/api/indices/register_bootstrap_route.js | 9 ++++++++- .../server/routes/api/lifecycle/register_create_route.js | 3 --- 2 files changed, 8 insertions(+), 4 deletions(-) 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 22902c925ccfa..dcd053e096c52 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 @@ -11,7 +11,14 @@ import { licensePreRoutingFactory } from '../../../lib/license_pre_routing_facto async function bootstrap(callWithRequest, payload) { await callWithRequest('indices.create', { - index: payload.indexName + index: payload.indexName, + body: { + aliases: { + [payload.aliasName]: { + is_write_alias: true + } + }, + } }); } 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 16ef4cd1451f0..14cf049454a34 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 @@ -38,9 +38,6 @@ async function updateIndexTemplate(callWithRequest, indexTemplatePatch) { // Fetch existing template const template = await getIndexTemplate(callWithRequest, indexTemplatePatch.indexTemplate); merge(template, { - aliases: { - [indexTemplatePatch.rolloverAlias]: {} - }, settings: { index: { number_of_shards: indexTemplatePatch.primaryShardCount, From c507a351bdaff41761a4c94d99994ff7506a1f39 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Mon, 27 Aug 2018 08:33:28 -0400 Subject: [PATCH 37/62] some copy edits for clarity --- .../components/template_selection/template_selection.js | 4 ++-- .../components/cold_phase/cold_phase.js | 6 +++--- .../policy_configuration/components/hot_phase/hot_phase.js | 2 +- .../components/warm_phase/warm_phase.js | 2 +- .../public/sections/wizard/components/review/review.js | 6 +++--- .../public/sections/wizard/wizard.js | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) 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 index 4f8acc5f7b6e5..832a420087dc7 100644 --- 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 @@ -99,7 +99,7 @@ export class TemplateSelection extends Component { /> setBootstrapEnabled(e.target.checked)} - label={Create an index for this template} + label={Create an index with this index template} /> {bootstrapEnabled ? ( 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 index a983f4f101335..737da8502a753 100644 --- 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 @@ -88,8 +88,8 @@ export class ColdPhase extends PureComponent { description={

- Your index is queried less frequently - and no longer needs to be on the most performant hardware. + A cold index is queried less frequently + and thus no longer needs to be on the most performant hardware.

{isShowingErrors ? ( @@ -156,7 +156,7 @@ export class ColdPhase extends PureComponent {

- This phase is required. Your index is being queried and actively written to. + This phase is required. A hot index is being queried and actively written to. You can optimize this phase for write throughput.

{isShowingErrors ? ( 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 index 265d3999bc020..f864c8a883747 100644 --- 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 @@ -203,7 +203,7 @@ export class WarmPhase extends PureComponent {

{`${affectedIndexTemplates.length} Index ${affectedIndexTemplates.length === 1 ? 'template' : 'templates'}`}

@@ -182,7 +182,7 @@ export class Review extends Component {

- {selectedIndexTemplateName} template changes + {selectedIndexTemplateName} index template changes

@@ -206,7 +206,7 @@ export class Review 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 template you + these changes in a new policy and only change the index template you selected.

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 index ed579e0e4aca0..9e85d6677389c 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js @@ -145,8 +145,8 @@ export class Wizard extends Component { ); } const steps = [ - this.createStep('Select a template', STEP_INDEX_TEMPLATE), - this.createStep('Configure a policy', STEP_POLICY_CONFIGURATION), + 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), ]; From f74e6027b7687eee2b690d376850446f6e3c0a14 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Mon, 27 Aug 2018 08:54:46 -0400 Subject: [PATCH 38/62] fixing issue with editing existing policy when rollover starts the warm phase --- .../public/store/selectors/policies.js | 10 ++-------- 1 file changed, 2 insertions(+), 8 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 d01304d29e5dd..d70604c63609f 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 @@ -97,14 +97,8 @@ export const phaseFromES = (phase, phaseName, defaultPolicy) => { const { size: after, units: afterUnits } = splitSizeAndUnits( phase.after ); - // If the after is set to 0s, it effectively means we are moving - // to the warm phase after rollover from the hot phase - if (phaseName === PHASE_WARM && after === 0) { - policy[PHASE_ROLLOVER_ENABLED] = true; - } else { - policy[PHASE_ROLLOVER_AFTER] = after; - policy[PHASE_ROLLOVER_AFTER_UNITS] = afterUnits; - } + policy[PHASE_ROLLOVER_AFTER] = after; + policy[PHASE_ROLLOVER_AFTER_UNITS] = afterUnits; } if (phase.actions) { From 1f3da343acef29cb64a3bb407181c8d2e4140889 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Mon, 27 Aug 2018 09:16:02 -0400 Subject: [PATCH 39/62] addressing PR feedback on server side code --- .../api/indices/register_get_affected_route.js | 15 ++++++++------- .../routes/api/nodes/register_details_route.js | 4 ++-- .../routes/api/nodes/register_list_route.js | 4 ++-- .../routes/api/templates/register_fetch_route.js | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) 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 e26d04600f15e..8f60bffb94b5a 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 @@ -27,25 +27,26 @@ async function getAffectedIndices( ) { const templates = await fetchTemplates(callWithRequest); - if (!templates || Object.keys(templates).length === 0 | templates.status === 404) { + if (!templates || Object.keys(templates).length === 0 || templates.status === 404) { return []; } const indexPatterns = Object.entries(templates).reduce((accum, [templateName, template]) => { - if (templateName === indexTemplateName) { - accum.push(...template.index_patterns); - } else if ( + const isMatchingTemplate = templateName === indexTemplateName; + const isMatchingPolicy = ( + policyName && template.settings && template.settings.index && template.settings.index.lifecycle && - (policyName && template.settings.index.lifecycle.name === policyName) - ) { + template.settings.index.lifecycle.name === policyName + ); + if (isMatchingTemplate || isMatchingPolicy) { accum.push(...template.index_patterns); } return accum; }, []); - if (!indexPatterns || indexPatterns.length === 0) { + if (indexPatterns.length === 0) { return []; } const indexParams = { 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 9ab30dd0f2f7e..1a0faff7ed5dd 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 @@ -12,7 +12,7 @@ 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, nodeAttrs) { +function findMatchingNodes(stats, nodeAttrs) { return Object.entries(stats.nodes).reduce((accum, [nodeId, stats]) => { const attributes = stats.attributes || {}; for (const [key, value] of Object.entries(attributes)) { @@ -48,7 +48,7 @@ export function registerDetailsRoute(server) { try { const stats = await fetchNodeStats(callWithRequest); - const response = formatStats(stats, request.params.nodeAttrs); + const response = findMatchingNodes (stats, request.params.nodeAttrs); reply(response); } catch (err) { if (isEsError(err)) { 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 7b82619665412..8e92e6570edcf 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 @@ -13,7 +13,7 @@ import { wrapEsError, wrapUnknownError } from '../../../lib/error_wrappers'; import { licensePreRoutingFactory } from'../../../lib/license_pre_routing_factory'; import { NODE_ATTRS_KEYS_TO_IGNORE } from './constants'; -function formatStats(stats) { +function convertStatsIntoList(stats) { return Object.entries(stats.nodes).reduce((accum, [nodeId, stats]) => { const attributes = stats.attributes || {}; for (const [key, value] of Object.entries(attributes)) { @@ -47,7 +47,7 @@ export function registerListRoute(server) { try { const stats = await fetchNodeStats(callWithRequest); - const response = formatStats(stats); + const response = convertStatsIntoList(stats); reply(response); } catch (err) { if (isEsError(err)) { 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 a8aaf38868e7a..1a4c5529b8da8 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 @@ -66,7 +66,7 @@ export function registerFetchRoute(server) { try { const hits = await fetchTemplates(callWithRequest); - const templates = formatTemplates(hits, callWithRequest); + const templates = await formatTemplates(hits, callWithRequest); reply(templates); } catch (err) { if (isEsError(err)) { From effd90983c19e4fc0057cf30b9909b4832f6b18a Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Mon, 27 Aug 2018 10:05:57 -0400 Subject: [PATCH 40/62] addressing PR feedback --- .../public/main.html | 2 +- .../policy_configuration.js | 3 - .../public/store/actions/nodes.js | 3 +- .../public/store/actions/policies.js | 4 +- .../public/store/constants.js | 5 +- .../public/store/defaults/cold_phase.js | 22 +++++++ .../public/store/defaults/delete_phase.js | 20 ++++++ .../public/store/defaults/hot_phase.js | 26 ++++++++ .../public/store/defaults/index.js | 10 +++ .../public/store/defaults/warm_phase.js | 32 +++++++++ .../store/middleware/auto_enable_phase.js | 8 +-- .../store/middleware/auto_set_node_attrs.js | 17 +++-- .../public/store/reducers/policies.js | 65 ++----------------- .../public/store/selectors/index_template.js | 13 +--- .../public/store/selectors/policies.js | 6 +- 15 files changed, 142 insertions(+), 94 deletions(-) create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/defaults/index.js create mode 100644 x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js diff --git a/x-pack/plugins/index_lifecycle_management/public/main.html b/x-pack/plugins/index_lifecycle_management/public/main.html index 36820f8e159ac..ca86144cbe934 100644 --- a/x-pack/plugins/index_lifecycle_management/public/main.html +++ b/x-pack/plugins/index_lifecycle_management/public/main.html @@ -1,3 +1,3 @@ - +
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 index a2ed77bd87f3b..f6beddab49c78 100644 --- 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 @@ -40,9 +40,6 @@ export class PolicyConfiguration extends Component { done: PropTypes.func.isRequired, back: 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, 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 index e357b6d6587f3..b806d1df3d380 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/actions/nodes.js @@ -7,8 +7,9 @@ import { createAction } from 'redux-actions'; import { toastNotifications } from 'ui/notify'; import { loadNodes, loadNodeDetails } from '../../api'; +import { SET_SELECTED_NODE_ATTRS } from '../constants'; -export const setSelectedNodeAttrs = createAction('SET_SELECTED_NODE_ATTRS'); +export const setSelectedNodeAttrs = createAction(SET_SELECTED_NODE_ATTRS); export const setSelectedPrimaryShardCount = createAction( 'SET_SELECTED_PRIMARY_SHARED_COUNT' ); 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 7d420d6e43b20..fccd46b449260 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 @@ -10,7 +10,7 @@ import { createAction } from 'redux-actions'; import { toastNotifications } from 'ui/notify'; import { loadPolicies } from '../../api'; - +import { SET_PHASE_DATA } from '../constants'; export const fetchedPolicies = createAction('FETCHED_POLICIES'); export const fetchPolicies = () => async dispatch => { let policies; @@ -29,4 +29,4 @@ 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 })); +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 index 3373946740d01..b8e918ef5e4b2 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/constants.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/constants.js @@ -4,9 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ - - - +export const SET_PHASE_DATA = 'SET_PHASE_DATA'; +export const SET_SELECTED_NODE_ATTRS = 'SET_SELECTED_NODE_ATTRS'; export const PHASE_HOT = 'hot'; export const PHASE_WARM = 'warm'; export const PHASE_COLD = 'cold'; diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js new file mode 100644 index 0000000000000..b5b54c02239ba --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.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 { + PHASE_ENABLED, + PHASE_ROLLOVER_AFTER, + PHASE_NODE_ATTRS, + PHASE_REPLICA_COUNT, + PHASE_ROLLOVER_AFTER_UNITS, + PHASE_ROLLOVER_ALIAS, +} from '../constants'; + +export const defaultColdPhase = { + [PHASE_ENABLED]: false, + [PHASE_ROLLOVER_ALIAS]: '', + [PHASE_ROLLOVER_AFTER]: '', + [PHASE_ROLLOVER_AFTER_UNITS]: 's', + [PHASE_NODE_ATTRS]: '', + [PHASE_REPLICA_COUNT]: '' +}; \ No newline at end of file diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js new file mode 100644 index 0000000000000..38653399035f6 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.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 { + PHASE_ENABLED, + PHASE_ROLLOVER_ENABLED, + PHASE_ROLLOVER_AFTER, + PHASE_ROLLOVER_AFTER_UNITS, + PHASE_ROLLOVER_ALIAS, +} from '../constants'; + +export const defaultDeletePhase = { + [PHASE_ENABLED]: false, + [PHASE_ROLLOVER_ENABLED]: false, + [PHASE_ROLLOVER_ALIAS]: '', + [PHASE_ROLLOVER_AFTER]: '', + [PHASE_ROLLOVER_AFTER_UNITS]: 's' +}; \ No newline at end of file diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js new file mode 100644 index 0000000000000..2053af0c3fc58 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under 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_ENABLED, + PHASE_ROLLOVER_ENABLED, + 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 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]: '', +}; \ No newline at end of file diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/index.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/index.js new file mode 100644 index 0000000000000..a92f98fa8e022 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/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 { defaultDeletePhase } from './delete_phase'; +export { defaultColdPhase } from './cold_phase'; +export { defaultHotPhase } from './hot_phase'; +export { defaultWarmPhase } from './warm_phase'; \ No newline at end of file diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js new file mode 100644 index 0000000000000..26db268641e37 --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.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 { + PHASE_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_ALIAS, + PHASE_SHRINK_ENABLED, + WARM_PHASE_ON_ROLLOVER +} from '../constants'; + +export const defaultWarmPhase = { + [PHASE_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_SHRINK_ENABLED]: true, + [PHASE_PRIMARY_SHARD_COUNT]: '', + [PHASE_REPLICA_COUNT]: '', + [WARM_PHASE_ON_ROLLOVER]: false +}; \ No newline at end of file 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 index 738be1fd7a56d..d7d390f608ccf 100644 --- 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 @@ -4,18 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - setPhaseData -} from '../actions'; +import { setPhaseData } from '../actions'; import { getPhaseData } from '../selectors'; -import { PHASE_ENABLED } from '../constants'; +import { SET_PHASE_DATA, PHASE_ENABLED } from '../constants'; const setsPerPhase = {}; export const autoEnablePhase = store => next => action => { const state = store.getState(); - if (action.type === setPhaseData().type) { + if (action.type === SET_PHASE_DATA) { const { phase } = action.payload; setsPerPhase[phase] = setsPerPhase[phase] || 0; setsPerPhase[phase]++; 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 index 5f0a43c31abdc..5d59ccd8c4fe7 100644 --- 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 @@ -4,22 +4,25 @@ * you may not use this file except in compliance with the Elastic License. */ -import { - setPhaseData, setSelectedNodeAttrs -} from '../actions'; +import { setPhaseData } from '../actions'; import { getPhaseData } from '../selectors'; -import { PHASE_WARM, PHASE_NODE_ATTRS, PHASE_COLD } from '../constants'; +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 === setSelectedNodeAttrs().type) { + 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 === setPhaseData().type) { + } else if (action.type === SET_PHASE_DATA) { const { phase, key, value } = action.payload; if (phase === PHASE_WARM && key === PHASE_NODE_ATTRS) { 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 0c147b7d14222..6afe1b4fc53ae 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 @@ -22,67 +22,14 @@ import { 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, - PHASE_SHRINK_ENABLED, - WARM_PHASE_ON_ROLLOVER } from '../constants'; -export const defaultWarmPhase = { - [PHASE_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_SHRINK_ENABLED]: true, - [PHASE_PRIMARY_SHARD_COUNT]: '', - [PHASE_REPLICA_COUNT]: '', - [WARM_PHASE_ON_ROLLOVER]: false -}; - -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_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' -}; - +import { + defaultColdPhase, + defaultDeletePhase, + defaultHotPhase, + defaultWarmPhase, +} from '../defaults'; export const defaultPolicy = { name: '', saveAsNew: true, 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 d470b6474660b..339d5380613ff 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 @@ -8,7 +8,7 @@ import { createSelector } from 'reselect'; -import { merge, cloneDeep } from 'lodash'; +import { get, merge, cloneDeep } from 'lodash'; import { getSaveAsNewPolicy, getSelectedPolicyName, @@ -19,7 +19,7 @@ import { } from '.'; import { getAliasName } from './general'; -export const getIndexTemplates = state => state.indexTemplate.indexTemplates; +export const getIndexTemplates = state => { return state.indexTemplate.indexTemplates || []; }; export const getIndexTemplateOptions = createSelector( [state => getIndexTemplates(state)], templates => { @@ -63,14 +63,7 @@ export const getFullSelectedIndexTemplate = state => state.indexTemplate.fullSel export const getAlias = state => { const indexTemplate = getSelectedIndexTemplate(state); - if (!indexTemplate) { - return undefined; - } - const { settings = {} } = indexTemplate; - if (settings.indexlifecycle) { - return settings.indexlifecycle.rollover_alias; - } - return undefined; + return get(indexTemplate, 'settings.indexlifecycle.rollover_alias'); }; // TODO: add createSelector 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 d70604c63609f..276928867ea2b 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 @@ -8,11 +8,11 @@ import { + defaultColdPhase, + defaultDeletePhase, defaultHotPhase, defaultWarmPhase, - defaultColdPhase, - defaultDeletePhase -} from '../reducers/policies'; +} from '../defaults'; import { PHASE_HOT, PHASE_WARM, From 8d644d078b0def13dbe56d34addae335ddb21146 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Mon, 27 Aug 2018 15:13:59 -0400 Subject: [PATCH 41/62] removing additional spaces from findMatchingNodes call --- .../server/routes/api/nodes/register_details_route.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 1a0faff7ed5dd..6cd882caf73a0 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 @@ -48,7 +48,7 @@ export function registerDetailsRoute(server) { try { const stats = await fetchNodeStats(callWithRequest); - const response = findMatchingNodes (stats, request.params.nodeAttrs); + const response = findMatchingNodes(stats, request.params.nodeAttrs); reply(response); } catch (err) { if (isEsError(err)) { From 32a72435fb78b6be485885c72aa7fa53c5098c1c Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Mon, 27 Aug 2018 15:16:13 -0400 Subject: [PATCH 42/62] changing template to index template in one more place --- .../components/template_selection/template_selection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 832a420087dc7..a86be2cde71e1 100644 --- 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 @@ -79,7 +79,7 @@ export class TemplateSelection extends Component { return ( Select a template} + title={

Select an index template

} fullWidth titleSize="s" description={ From 8592496692c5ed64fc5b51658cd4904c25e7192f Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Thu, 30 Aug 2018 10:37:16 -0400 Subject: [PATCH 43/62] fixing issue with error message showing when bootstrap is successful --- x-pack/plugins/index_lifecycle_management/public/api/index.js | 2 +- .../public/sections/wizard/wizard.js | 4 ++-- 2 files changed, 3 insertions(+), 3 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 a67e3c22ae48b..778a33e389549 100644 --- a/x-pack/plugins/index_lifecycle_management/public/api/index.js +++ b/x-pack/plugins/index_lifecycle_management/public/api/index.js @@ -46,7 +46,7 @@ export async function saveLifecycle(lifecycle, indexTemplatePatch) { export async function bootstrap(indexName, aliasName) { const response = await httpClient.post(`${apiPrefix}/indices/bootstrap`, { indexName, aliasName }); - return response.data; + return response.status === 200; } export async function getAffectedIndices(indexTemplateName, policyName) { 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 index 9e85d6677389c..a0dff6e332e30 100644 --- a/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js +++ b/x-pack/plugins/index_lifecycle_management/public/sections/wizard/wizard.js @@ -79,8 +79,8 @@ export class Wizard extends Component { return; } - const response = await bootstrap(indexName, aliasName); - if (response && response.acknowledged) { + const bootstrapSuccess = await bootstrap(indexName, aliasName); + if (bootstrapSuccess) { toastNotifications.addSuccess( 'Successfully bootstrapped an index and alias' ); From 6201e608c8d114004a4e898ca6512d00e7ad320d Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Thu, 30 Aug 2018 10:58:57 -0400 Subject: [PATCH 44/62] fixing node options for warm and cold phase --- .../index_template/components/configuration/configuration.js | 2 +- .../components/template_selection/template_selection.js | 2 +- .../index_lifecycle_management/public/store/selectors/nodes.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 index ac4d153b08f15..f1f1e28f3e6ec 100644 --- 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 @@ -113,7 +113,7 @@ export class Configuration extends Component { await setSelectedNodeAttrs(e.target.value); validate(); }} - options={[{ text: 'Default allocation (don\'t use attributes)', value: '' }, ...nodeOptions]} + options={nodeOptions} /> a.value.localeCompare(b.value)); - return options; + return [{ text: 'Default allocation (don\'t use attributes)', value: '' }, ...options]; } ); From 1282054d2f03e49ee7e72b0ae1a65de8936bf815 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Thu, 30 Aug 2018 13:55:07 -0400 Subject: [PATCH 45/62] adding seconds to duration fields to match what ES supports --- .../policy_configuration/components/cold_phase/cold_phase.js | 3 ++- .../components/delete_phase/delete_phase.js | 3 ++- .../policy_configuration/components/hot_phase/hot_phase.js | 3 ++- .../policy_configuration/components/warm_phase/warm_phase.js | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) 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 index 737da8502a753..9380ce4aa050e 100644 --- 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 @@ -146,7 +146,8 @@ export class ColdPhase extends PureComponent { } options={[ { value: 'd', text: 'days' }, - { value: 'h', text: 'hours' } + { value: 'h', text: 'hours' }, + { value: 's', text: 'seconds' }, ]} /> 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 index 52226029b1111..ec2bdb72c9007 100644 --- 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 @@ -132,7 +132,8 @@ export class DeletePhase extends PureComponent { } options={[ { value: 'd', text: 'days' }, - { value: 'h', text: 'hours' } + { value: 'h', text: 'hours' }, + { value: 's', text: 'seconds' }, ]} /> 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 index 659dadb0d092c..876be9e46fbad 100644 --- 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 @@ -196,7 +196,8 @@ export class HotPhase extends PureComponent { }} options={[ { value: 'd', text: 'days' }, - { value: 'h', text: 'hours' } + { value: 'h', text: 'hours' }, + { value: 's', text: 'seconds' }, ]} /> 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 index f864c8a883747..ef62533ae8b0d 100644 --- 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 @@ -193,6 +193,7 @@ export class WarmPhase extends PureComponent { options={[ { value: 'd', text: 'days' }, { value: 'h', text: 'hours' }, + { value: 's', text: 'seconds' }, ]} /> From de40de48dc5f5ad39e3b1f2efe178e49999f0cd5 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Fri, 31 Aug 2018 08:46:30 -0400 Subject: [PATCH 46/62] changing icon for enabled steps so it does not look like an error indicator --- .../policy_configuration/components/cold_phase/cold_phase.js | 4 ++-- .../components/delete_phase/delete_phase.js | 4 ++-- .../policy_configuration/components/hot_phase/hot_phase.js | 4 ++-- .../policy_configuration/components/warm_phase/warm_phase.js | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) 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 index 9380ce4aa050e..e9caa9574d6bb 100644 --- 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 @@ -18,7 +18,7 @@ import { EuiSelect, EuiButtonEmpty, EuiDescribedFormGroup, - EuiBetaBadge, + EuiIcon, EuiButton, } from '@elastic/eui'; import { @@ -80,7 +80,7 @@ export class ColdPhase extends PureComponent {
Cold phase{' '} {phaseData[PHASE_ENABLED] ? ( - + ) : null}
} 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 index ec2bdb72c9007..7a75b2345ec0c 100644 --- 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 @@ -21,7 +21,7 @@ import { EuiFieldNumber, EuiSelect, EuiDescribedFormGroup, - EuiBetaBadge, + EuiIcon, EuiButton, } from '@elastic/eui'; import { @@ -63,7 +63,7 @@ export class DeletePhase extends PureComponent {
Delete phase{' '} {phaseData[PHASE_ENABLED] ? ( - + ) : null}
} 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 index 876be9e46fbad..ce6ac41846122 100644 --- 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 @@ -18,7 +18,7 @@ import { EuiSwitch, EuiFormRow, EuiDescribedFormGroup, - EuiBetaBadge, + EuiIcon, } from '@elastic/eui'; import { LearnMoreLink } from '../../../../../../components/learn_more_link'; import { @@ -70,7 +70,7 @@ export class HotPhase extends PureComponent { title={
Hot phase{' '} - +
} titleSize="s" 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 index ef62533ae8b0d..7daa981e264ee 100644 --- 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 @@ -19,7 +19,7 @@ import { EuiSwitch, EuiButtonEmpty, EuiDescribedFormGroup, - EuiBetaBadge, + EuiIcon, EuiButton, } from '@elastic/eui'; import { @@ -108,7 +108,7 @@ export class WarmPhase extends PureComponent {
Warm phase{' '} {phaseData[PHASE_ENABLED] ? ( - + ) : null}
} From 121c1965a5feea76951e027fa429a001bf6fb8fa Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Fri, 31 Aug 2018 08:59:38 -0400 Subject: [PATCH 47/62] adjusting icon color for enabled lifecycle steps --- .../policy_configuration/components/cold_phase/cold_phase.js | 2 +- .../components/delete_phase/delete_phase.js | 2 +- .../policy_configuration/components/hot_phase/hot_phase.js | 2 +- .../policy_configuration/components/warm_phase/warm_phase.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) 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 index e9caa9574d6bb..09ce094c8caf8 100644 --- 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 @@ -80,7 +80,7 @@ export class ColdPhase extends PureComponent {
Cold phase{' '} {phaseData[PHASE_ENABLED] ? ( - + ) : null}
} 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 index 7a75b2345ec0c..aef3aed0240ad 100644 --- 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 @@ -63,7 +63,7 @@ export class DeletePhase extends PureComponent {
Delete phase{' '} {phaseData[PHASE_ENABLED] ? ( - + ) : null}
} 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 index ce6ac41846122..27c692ea0d914 100644 --- 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 @@ -70,7 +70,7 @@ export class HotPhase extends PureComponent { title={
Hot phase{' '} - +
} titleSize="s" 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 index 7daa981e264ee..14ba9aa5ca494 100644 --- 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 @@ -108,7 +108,7 @@ export class WarmPhase extends PureComponent {
Warm phase{' '} {phaseData[PHASE_ENABLED] ? ( - + ) : null}
} From 280d44c78ef60e89078a6c2885f4501421c9dd3a Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Fri, 31 Aug 2018 09:13:52 -0400 Subject: [PATCH 48/62] fixing issue with editing an existing policy with warm phase on rollover enabled --- .../public/store/selectors/policies.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 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 276928867ea2b..76ff6759ebf7a 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 @@ -32,7 +32,8 @@ import { PHASE_REPLICA_COUNT, PHASE_ENABLED, PHASE_ATTRIBUTES_THAT_ARE_NUMBERS, - MAX_SIZE_TYPE_DOCUMENT + MAX_SIZE_TYPE_DOCUMENT, + WARM_PHASE_ON_ROLLOVER } from '../constants'; import { getIndexTemplates } from '.'; @@ -94,11 +95,15 @@ export const phaseFromES = (phase, phaseName, defaultPolicy) => { policy[PHASE_ROLLOVER_ENABLED] = false; if (phase.after) { - const { size: after, units: afterUnits } = splitSizeAndUnits( - phase.after - ); - policy[PHASE_ROLLOVER_AFTER] = after; - policy[PHASE_ROLLOVER_AFTER_UNITS] = afterUnits; + if (phaseName === PHASE_WARM && phase.after === '0s') { + policy[WARM_PHASE_ON_ROLLOVER] = true; + } else { + const { size: after, units: afterUnits } = splitSizeAndUnits( + phase.after + ); + policy[PHASE_ROLLOVER_AFTER] = after; + policy[PHASE_ROLLOVER_AFTER_UNITS] = afterUnits; + } } if (phase.actions) { From ea06e41c17935b5780c5ac035aa68ae564a5bce8 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Fri, 31 Aug 2018 09:21:17 -0400 Subject: [PATCH 49/62] fixing issue with default unit for age dropdowns --- .../public/store/defaults/cold_phase.js | 2 +- .../public/store/defaults/delete_phase.js | 2 +- .../public/store/defaults/hot_phase.js | 2 +- .../public/store/defaults/warm_phase.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js index b5b54c02239ba..66750a824cca8 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/cold_phase.js @@ -16,7 +16,7 @@ export const defaultColdPhase = { [PHASE_ENABLED]: false, [PHASE_ROLLOVER_ALIAS]: '', [PHASE_ROLLOVER_AFTER]: '', - [PHASE_ROLLOVER_AFTER_UNITS]: 's', + [PHASE_ROLLOVER_AFTER_UNITS]: 'd', [PHASE_NODE_ATTRS]: '', [PHASE_REPLICA_COUNT]: '' }; \ No newline at end of file diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js index 38653399035f6..236e20c0c36d4 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/delete_phase.js @@ -16,5 +16,5 @@ export const defaultDeletePhase = { [PHASE_ROLLOVER_ENABLED]: false, [PHASE_ROLLOVER_ALIAS]: '', [PHASE_ROLLOVER_AFTER]: '', - [PHASE_ROLLOVER_AFTER_UNITS]: 's' + [PHASE_ROLLOVER_AFTER_UNITS]: 'd' }; \ No newline at end of file diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js index 2053af0c3fc58..d0e45a963505b 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/hot_phase.js @@ -19,7 +19,7 @@ export const defaultHotPhase = { [PHASE_ROLLOVER_ENABLED]: true, [PHASE_ROLLOVER_ALIAS]: '', [PHASE_ROLLOVER_MAX_AGE]: '', - [PHASE_ROLLOVER_MAX_AGE_UNITS]: 's', + [PHASE_ROLLOVER_MAX_AGE_UNITS]: 'd', [PHASE_ROLLOVER_MAX_SIZE_STORED]: '', [PHASE_ROLLOVER_MAX_SIZE_STORED_UNITS]: 'gb', [PHASE_ROLLOVER_MAX_DOC_SIZE]: '', diff --git a/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js b/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js index 26db268641e37..84ffa9c742043 100644 --- a/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js +++ b/x-pack/plugins/index_lifecycle_management/public/store/defaults/warm_phase.js @@ -23,7 +23,7 @@ export const defaultWarmPhase = { [PHASE_FORCE_MERGE_SEGMENTS]: '', [PHASE_FORCE_MERGE_ENABLED]: false, [PHASE_ROLLOVER_AFTER]: '', - [PHASE_ROLLOVER_AFTER_UNITS]: 's', + [PHASE_ROLLOVER_AFTER_UNITS]: 'd', [PHASE_NODE_ATTRS]: '', [PHASE_SHRINK_ENABLED]: true, [PHASE_PRIMARY_SHARD_COUNT]: '', From 7dcefbce271b19dcdd945f328ddb7b85c54cdd5a Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Fri, 31 Aug 2018 10:10:14 -0400 Subject: [PATCH 50/62] fixing issues with shrink action serialization and deserialization --- .../public/store/selectors/policies.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 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 76ff6759ebf7a..d607e2c1a1745 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 @@ -33,7 +33,8 @@ import { PHASE_ENABLED, PHASE_ATTRIBUTES_THAT_ARE_NUMBERS, MAX_SIZE_TYPE_DOCUMENT, - WARM_PHASE_ON_ROLLOVER + WARM_PHASE_ON_ROLLOVER, + PHASE_SHRINK_ENABLED } from '../constants'; import { getIndexTemplates } from '.'; @@ -105,7 +106,9 @@ export const phaseFromES = (phase, phaseName, defaultPolicy) => { policy[PHASE_ROLLOVER_AFTER_UNITS] = afterUnits; } } - + if (phaseName === PHASE_WARM) { + phase[PHASE_SHRINK_ENABLED] = phase.actions && phase.actions.shrink; + } if (phase.actions) { const actions = phase.actions; @@ -221,7 +224,7 @@ export const phaseToES = (state, phase) => { }; } - if (isNumber(phase[PHASE_PRIMARY_SHARD_COUNT])) { + if (phase[PHASE_SHRINK_ENABLED] && isNumber(phase[PHASE_PRIMARY_SHARD_COUNT])) { esPhase.actions.shrink = { number_of_shards: phase[PHASE_PRIMARY_SHARD_COUNT] }; From 7fb7509b489d3f5941040060bed99a305be86795 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Fri, 31 Aug 2018 12:10:13 -0400 Subject: [PATCH 51/62] fixing issue with deserialization of ES policy for shrink --- .../public/store/selectors/policies.js | 3 +-- 1 file changed, 1 insertion(+), 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 d607e2c1a1745..fcb4b402cb15c 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 @@ -107,7 +107,7 @@ export const phaseFromES = (phase, phaseName, defaultPolicy) => { } } if (phaseName === PHASE_WARM) { - phase[PHASE_SHRINK_ENABLED] = phase.actions && phase.actions.shrink; + policy[PHASE_SHRINK_ENABLED] = !!(phase.actions && phase.actions.shrink); } if (phase.actions) { const actions = phase.actions; @@ -157,7 +157,6 @@ export const phaseFromES = (phase, phaseName, defaultPolicy) => { policy[PHASE_REPLICA_COUNT] = replicas.number_of_replicas; } } - return policy; }; From 797675d7cd4435531ba8882702f837e72735fd72 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Fri, 31 Aug 2018 12:23:38 -0400 Subject: [PATCH 52/62] removing shrink option from UI when primary shard count is not greater than 1 for hot phase --- .../warm_phase/warm_phase.container.js | 4 +- .../components/warm_phase/warm_phase.js | 57 +++++++++---------- 2 files changed, 29 insertions(+), 32 deletions(-) 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 index b224e9b232769..95176ef3498ca 100644 --- 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 @@ -21,8 +21,8 @@ import { PHASE_WARM, PHASE_HOT, PHASE_ROLLOVER_ENABLED } from '../../../../../.. export const WarmPhase = connect( state => ({ phaseData: getPhase(state, PHASE_WARM), - hotPhaseReplicaCount: getSelectedReplicaCount(state), - hotPhasePrimaryShardCount: getSelectedPrimaryShardCount(state), + 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/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 index 14ba9aa5ca494..81943d366cec7 100644 --- 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 @@ -71,14 +71,8 @@ export class WarmPhase extends PureComponent { [PHASE_ROLLOVER_AFTER_UNITS]: PropTypes.string.isRequired, }).isRequired, - hotPhaseReplicaCount: PropTypes.oneOfType([ - PropTypes.number, - PropTypes.string, - ]).isRequired, - hotPhasePrimaryShardCount: PropTypes.oneOfType([ - PropTypes.number, - PropTypes.string, - ]).isRequired, + hotPhaseReplicaCount: PropTypes.number.isRequired, + hotPhasePrimaryShardCount: PropTypes.number.isRequired, nodeOptions: PropTypes.array.isRequired, }; @@ -266,30 +260,33 @@ export class WarmPhase extends PureComponent { - - - -

Shrink

-
- - - Shrink the index into a new index with fewer primary shards.{' '} - - - + {hotPhaseReplicaCount > 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" - /> + { + await setPhaseData(PHASE_SHRINK_ENABLED, e.target.checked); + validate(); + }} + label="Shrink index" + /> +
+ ) : null } From 02dc6cdc76912793a471b744473d694523f57162 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Tue, 4 Sep 2018 09:31:42 -0400 Subject: [PATCH 53/62] going straight to create policy when no policies exist --- .../components/policy_selection/policy_selection.js | 8 +++++--- .../public/store/actions/policies.js | 10 +++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) 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 index 3939ccf8424f7..f85d992a3b8f3 100644 --- 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 @@ -25,10 +25,9 @@ export class PolicySelection extends Component { policies: PropTypes.array.isRequired, }; - componentWillMount() { + componentDidMount() { this.props.fetchPolicies(); } - selectPolicy(policyName) { const policy = this.props.policies.find(policy => policy.name === policyName); this.props.setSelectedPolicy(policy); @@ -38,6 +37,9 @@ export class PolicySelection extends Component { const { policies, selectedPolicyName } = this.props; let existingPoliciesSelect; const policiesExist = policies.length > 0; + if (!policiesExist) { + return null; + } if (policiesExist) { const options = policies.map(item => ({ value: item.name, text: item.name })); options.unshift({ @@ -61,7 +63,7 @@ export class PolicySelection extends Component { return ( {policiesExist ? 'Select or c' : 'C'}reate a policy} + title={

Select or create a policy

} titleSize="s" description={`An index lifecycle policy is a blueprint for transitioning your data over time. 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 fccd46b449260..72132e13f4d93 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 @@ -12,6 +12,10 @@ import { toastNotifications } from 'ui/notify'; import { loadPolicies } from '../../api'; import { SET_PHASE_DATA } from '../constants'; export const fetchedPolicies = createAction('FETCHED_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 fetchPolicies = () => async dispatch => { let policies; try { @@ -22,11 +26,11 @@ export const fetchPolicies = () => async dispatch => { } dispatch(fetchedPolicies(policies)); + if (policies.length === 0) { + dispatch(setSelectedPolicy()); + } return 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 })); From d2a67632bf98dffb6fe0b688cdf1ede5918d30db Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Tue, 4 Sep 2018 13:41:04 -0400 Subject: [PATCH 54/62] improving lifecycle policy selection --- .../policy_configuration.container.js | 12 ++++--- .../policy_configuration.js | 27 ++++++++++++---- .../policy_selection.container.js | 3 +- .../policy_selection/policy_selection.js | 32 +++++++++---------- .../public/store/actions/policies.js | 1 + .../public/store/reducers/policies.js | 4 +++ 6 files changed, 52 insertions(+), 27 deletions(-) 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 index 29da1a719d9b5..2db2af570ed44 100644 --- 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 @@ -15,14 +15,16 @@ import { getAliasName, getSaveAsNewPolicy, getSelectedOriginalPolicyName, - getIsSelectedPolicySet + getIsSelectedPolicySet, + getPolicies } from '../../../../store/selectors'; import { setBootstrapEnabled, setIndexName, setAliasName, setSelectedPolicyName, - setSaveAsNewPolicy + setSaveAsNewPolicy, + unsetSelectedPolicy } from '../../../../store/actions'; export const PolicyConfiguration = connect( @@ -35,13 +37,15 @@ export const PolicyConfiguration = connect( indexName: getIndexName(state), aliasName: getAliasName(state), saveAsNewPolicy: getSaveAsNewPolicy(state), - originalPolicyName: getSelectedOriginalPolicyName(state) + originalPolicyName: getSelectedOriginalPolicyName(state), + hasExistingPolicies: getPolicies(state).length > 0 }), { setBootstrapEnabled, setIndexName, setAliasName, setSelectedPolicyName, - setSaveAsNewPolicy + setSaveAsNewPolicy, + 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 index f6beddab49c78..91420828e7734 100644 --- 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 @@ -15,6 +15,8 @@ import { EuiHorizontalRule, EuiButton, EuiButtonEmpty, + EuiFlexGroup, + EuiFlexItem, } from '@elastic/eui'; import { HotPhase } from './components/hot_phase'; import { WarmPhase } from './components/warm_phase'; @@ -63,7 +65,9 @@ export class PolicyConfiguration extends Component { const noErrors = !hasErrors(this.props.errors); return noErrors; }; - + componentDidMount() { + window.scrollTo(0, 0); + } submit = async () => { this.setState({ isShowingErrors: true }); if (await this.validate()) { @@ -84,6 +88,8 @@ export class PolicyConfiguration extends Component { selectedPolicyName, isSelectedPolicySet, errors, + unsetSelectedPolicy, + hasExistingPolicies } = this.props; const { isShowingErrors } = this.state; @@ -98,11 +104,20 @@ export class PolicyConfiguration extends Component {
- -

- {!selectedPolicyName ? 'Create a policy' : `Edit policy ${selectedPolicyName}`} -

-
+ + + +

+ {!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.

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 index 618cd3a128bbc..59ce80fc1f0a4 100644 --- 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 @@ -10,7 +10,7 @@ import { connect } from 'react-redux'; import { PolicySelection as PresentationComponent } from './policy_selection'; import { - getPolicies, getSelectedPolicyName, + getPolicies, getIsSelectedPolicySet, getSelectedPolicyName, } from '../../../../store/selectors'; import { fetchPolicies, @@ -19,6 +19,7 @@ import { export const PolicySelection = connect( state => ({ + isSelectedPolicySet: getIsSelectedPolicySet(state), policies: getPolicies(state), selectedPolicyName: getSelectedPolicyName(state), }), 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 index f85d992a3b8f3..c26768b33495f 100644 --- 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 @@ -34,18 +34,15 @@ export class PolicySelection extends Component { } render() { - const { policies, selectedPolicyName } = this.props; - let existingPoliciesSelect; + const { isSelectedPolicySet, policies, selectedPolicyName } = this.props; const policiesExist = policies.length > 0; - if (!policiesExist) { + if (isSelectedPolicySet) { return null; } + let existingPoliciesSelect; if (policiesExist) { const options = policies.map(item => ({ value: item.name, text: item.name })); - options.unshift({ - value: '', - text: '-- New Policy --', - }); + options.unshift({ value: '', text: 'Select an existing policy' }); existingPoliciesSelect = ( @@ -63,21 +60,24 @@ export class PolicySelection extends Component { return ( Select or create a policy} + title={

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} - - - this.selectPolicy()}>Create new policy - - - + + + {existingPoliciesSelect} + +

- OR -

+
+ + this.selectPolicy()}>Create lifecycle policy + +
+
); } 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 72132e13f4d93..74f79799108c0 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 @@ -13,6 +13,7 @@ import { loadPolicies } from '../../api'; import { SET_PHASE_DATA } from '../constants'; export const fetchedPolicies = createAction('FETCHED_POLICIES'); export const setSelectedPolicy = createAction('SET_SELECTED_POLICY'); +export const unsetSelectedPolicy = createAction('UNSET_SELECTED_POLICY'); export const setSelectedPolicyName = createAction('SET_SELECTED_POLICY_NAME'); export const setSaveAsNewPolicy = createAction('SET_SAVE_AS_NEW_POLICY'); 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 6afe1b4fc53ae..b304951b18ef1 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 @@ -11,6 +11,7 @@ import { handleActions } from 'redux-actions'; import { fetchedPolicies, setSelectedPolicy, + unsetSelectedPolicy, setSelectedPolicyName, setSaveAsNewPolicy, setPhaseData @@ -77,6 +78,9 @@ export const policies = handleActions( } }; }, + [unsetSelectedPolicy]() { + return defaultState; + }, [setSelectedPolicyName](state, { payload: name }) { return { ...state, From a327cb8097f060bde95fae5cb3a1ef9aa0a8a934 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Tue, 4 Sep 2018 13:50:23 -0400 Subject: [PATCH 55/62] adding active badge instead of checkmark for active lifecycle policy phases --- .../policy_configuration/components/cold_phase/cold_phase.js | 4 ++-- .../components/delete_phase/delete_phase.js | 4 ++-- .../policy_configuration/components/warm_phase/warm_phase.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) 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 index 09ce094c8caf8..05f385e57dea8 100644 --- 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 @@ -18,7 +18,7 @@ import { EuiSelect, EuiButtonEmpty, EuiDescribedFormGroup, - EuiIcon, + EuiBadge, EuiButton, } from '@elastic/eui'; import { @@ -80,7 +80,7 @@ export class ColdPhase extends PureComponent {
Cold phase{' '} {phaseData[PHASE_ENABLED] ? ( - + Active ) : null}
} 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 index aef3aed0240ad..c714990824fa5 100644 --- 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 @@ -21,7 +21,7 @@ import { EuiFieldNumber, EuiSelect, EuiDescribedFormGroup, - EuiIcon, + EuiBadge, EuiButton, } from '@elastic/eui'; import { @@ -63,7 +63,7 @@ export class DeletePhase extends PureComponent {
Delete phase{' '} {phaseData[PHASE_ENABLED] ? ( - + Active ) : null}
} 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 index 81943d366cec7..0084bbbee82e3 100644 --- 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 @@ -19,7 +19,7 @@ import { EuiSwitch, EuiButtonEmpty, EuiDescribedFormGroup, - EuiIcon, + EuiBadge, EuiButton, } from '@elastic/eui'; import { @@ -102,7 +102,7 @@ export class WarmPhase extends PureComponent {
Warm phase{' '} {phaseData[PHASE_ENABLED] ? ( - + Active ) : null}
} From f508177681c11659b5fd59a878e6a9c61e31c237 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Tue, 4 Sep 2018 15:32:24 -0400 Subject: [PATCH 56/62] some cleanup of unneeded properties and only showing save as new when it is appropriate --- .../components/hot_phase/hot_phase.js | 4 +- .../components/warm_phase/warm_phase.js | 2 +- .../policy_configuration.container.js | 4 -- .../policy_configuration.js | 2 - .../components/review/review.container.js | 2 + .../wizard/components/review/review.js | 37 +++++++++++-------- .../public/store/reducers/policies.js | 1 + .../public/store/selectors/policies.js | 2 + 8 files changed, 29 insertions(+), 25 deletions(-) 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 index 27c692ea0d914..7af9cb5a6ce46 100644 --- 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 @@ -18,7 +18,7 @@ import { EuiSwitch, EuiFormRow, EuiDescribedFormGroup, - EuiIcon, + EuiBadge, } from '@elastic/eui'; import { LearnMoreLink } from '../../../../../../components/learn_more_link'; import { @@ -70,7 +70,7 @@ export class HotPhase extends PureComponent { title={
Hot phase{' '} - + Active
} titleSize="s" 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 index 0084bbbee82e3..dbdb67220f577 100644 --- 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 @@ -138,7 +138,7 @@ export class WarmPhase extends PureComponent { validate(); }} > - Remove warm phase + Deactivate warm phase
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 index 2db2af570ed44..233e39776265a 100644 --- 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 @@ -13,7 +13,6 @@ import { getBootstrapEnabled, getIndexName, getAliasName, - getSaveAsNewPolicy, getSelectedOriginalPolicyName, getIsSelectedPolicySet, getPolicies @@ -23,7 +22,6 @@ import { setIndexName, setAliasName, setSelectedPolicyName, - setSaveAsNewPolicy, unsetSelectedPolicy } from '../../../../store/actions'; @@ -36,7 +34,6 @@ export const PolicyConfiguration = connect( bootstrapEnabled: getBootstrapEnabled(state), indexName: getIndexName(state), aliasName: getAliasName(state), - saveAsNewPolicy: getSaveAsNewPolicy(state), originalPolicyName: getSelectedOriginalPolicyName(state), hasExistingPolicies: getPolicies(state).length > 0 }), @@ -45,7 +42,6 @@ export const PolicyConfiguration = connect( setIndexName, setAliasName, setSelectedPolicyName, - setSaveAsNewPolicy, 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 index 91420828e7734..df406b14c76d0 100644 --- 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 @@ -35,7 +35,6 @@ import { PolicySelection } from '../policy_selection/policy_selection.container' 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, @@ -43,7 +42,6 @@ export class PolicyConfiguration extends Component { back: PropTypes.func.isRequired, validate: PropTypes.func.isRequired, selectedPolicyName: PropTypes.string.isRequired, - saveAsNewPolicy: PropTypes.bool.isRequired, errors: PropTypes.object.isRequired, bootstrapEnabled: PropTypes.bool.isRequired, indexName: PropTypes.string.isRequired, 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 index dbc2fcae7f535..044648dbbcabd 100644 --- 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 @@ -21,6 +21,7 @@ import { getBootstrapEnabled, getIndexName, getPolicies, + getIsNewPolicy } from '../../../../store/selectors'; import { setSelectedPolicyName, @@ -42,6 +43,7 @@ export const Review = connect( selectedPolicyName: getSelectedPolicyName(state), saveAsNewPolicy: getSaveAsNewPolicy(state), originalPolicyName: getSelectedOriginalPolicyName(state), + isNewPolicy: getIsNewPolicy(state), /* start might go away */ indexName: getIndexName(state), 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 e7248ab8b3107..8191bd7867c3a 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 @@ -125,6 +125,7 @@ export class Review extends Component { bootstrapEnabled, aliasName, policies, + isNewPolicy } = this.props; const { affectedIndices, isLoadingAffectedIndices, isShowingErrors } = this.state; @@ -213,24 +214,27 @@ export class Review extends Component { ) : null } - - { - await setSaveAsNewPolicy(e.target.checked); - validate(); - }} - label={ - - Save this as a new policy - - } - /> - + { isNewPolicy ? null : ( + + { + await setSaveAsNewPolicy(e.target.checked); + validate(); + }} + label={ + + Save this as a new policy + + } + /> + + )} + ) : null} - {saveAsNewPolicy ? ( + {saveAsNewPolicy || isNewPolicy ? (

Save your work

@@ -267,6 +271,7 @@ export class Review extends Component { color="secondary" iconType="check" onClick={() => done(lifecycle)} + disabled={!selectedPolicyName} > Looks good, save changes 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 b304951b18ef1..5b2c288858385 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 @@ -34,6 +34,7 @@ import { export const defaultPolicy = { name: '', saveAsNew: true, + isNew: true, phases: { [PHASE_HOT]: defaultHotPhase, [PHASE_WARM]: defaultWarmPhase, 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 fcb4b402cb15c..12fcededa6f09 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 @@ -39,6 +39,8 @@ import { import { getIndexTemplates } from '.'; 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; From f5316bb6b1e62efb282b1a7ac2b873ac45ebda75 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Tue, 4 Sep 2018 15:35:07 -0400 Subject: [PATCH 57/62] removing stray fullWidth attribute --- .../wizard/components/policy_selection/policy_selection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index c26768b33495f..e153d9fd1ce03 100644 --- 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 @@ -68,7 +68,7 @@ export class PolicySelection extends Component { fullWidth > - + {existingPoliciesSelect}

- OR -

From 979cd62b3787b6f87cd5f9099768f7ca030e8789 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Wed, 5 Sep 2018 09:39:50 -0400 Subject: [PATCH 58/62] adding missing minimum for replica count for warm phase --- .../policy_configuration/components/warm_phase/warm_phase.js | 1 + 1 file changed, 1 insertion(+) 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 index dbdb67220f577..d18813b1595b6 100644 --- 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 @@ -239,6 +239,7 @@ export class WarmPhase extends PureComponent { await setPhaseData(PHASE_REPLICA_COUNT, e.target.value); validate(); }} + min={0} />
From 873d65b6a66ef4afe0c7159e69c90983a5fda384 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Wed, 5 Sep 2018 14:52:07 -0400 Subject: [PATCH 59/62] adding scroll to top for review step --- .../public/sections/wizard/components/review/review.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 8191bd7867c3a..20302c08de61f 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 @@ -65,7 +65,9 @@ export class Review extends Component { this.currentFetchTimeout = null; } - + componentDidMount() { + window.scrollTo(0, 0); + } fetchAffectedIndices = () => { if (this.currentFetchTimeout) { clearTimeout(this.currentFetchTimeout); From 8d658a5279956aebde4c8e4ac1c2197cecaae800 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Thu, 6 Sep 2018 08:17:28 -0400 Subject: [PATCH 60/62] fixing issue with start warm phase after rollover introduced by time representaiton change from ES --- .../public/store/selectors/policies.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 12fcededa6f09..3b7733e6c4fd0 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 @@ -98,7 +98,7 @@ export const phaseFromES = (phase, phaseName, defaultPolicy) => { policy[PHASE_ROLLOVER_ENABLED] = false; if (phase.after) { - if (phaseName === PHASE_WARM && phase.after === '0s') { + if (phaseName === PHASE_WARM && phase.after === '0ms') { policy[WARM_PHASE_ON_ROLLOVER] = true; } else { const { size: after, units: afterUnits } = splitSizeAndUnits( From dcba51389c2c5db5e50ca54ff15a7ef6eb3d4c94 Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Thu, 6 Sep 2018 08:29:25 -0400 Subject: [PATCH 61/62] making shrink options not show for primary shard count of 1 as you can't shrink in that situation --- .../components/warm_phase/warm_phase.js | 146 +++++++----------- .../public/store/selectors/lifecycle.js | 20 ++- 2 files changed, 70 insertions(+), 96 deletions(-) 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 index d18813b1595b6..478ea106c89b7 100644 --- 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 @@ -51,23 +51,13 @@ export class WarmPhase extends PureComponent { [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_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_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, @@ -110,8 +100,8 @@ export class WarmPhase extends PureComponent { description={

- Your index becomes read-only when it enters the warm phase. - You can optimize this phase for search. + Your index becomes read-only when it enters the warm phase. You can optimize this + phase for search.

{isShowingErrors ? ( @@ -125,8 +115,6 @@ export class WarmPhase extends PureComponent { fullWidth > - - {phaseData[PHASE_ENABLED] ? ( @@ -178,10 +166,7 @@ export class WarmPhase extends PureComponent { { - await setPhaseData( - PHASE_ROLLOVER_AFTER_UNITS, - e.target.value - ); + await setPhaseData(PHASE_ROLLOVER_AFTER_UNITS, e.target.value); validate(); }} options={[ @@ -206,9 +191,7 @@ export class WarmPhase extends PureComponent { phaseData[PHASE_NODE_ATTRS] ? ( - showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS]) - } + onClick={() => showNodeDetailsFlyout(phaseData[PHASE_NODE_ATTRS])} > View node details @@ -248,10 +231,7 @@ export class WarmPhase extends PureComponent { { - await setPhaseData( - PHASE_REPLICA_COUNT, - hotPhaseReplicaCount - ); + await setPhaseData(PHASE_REPLICA_COUNT, hotPhaseReplicaCount); validate(); }} > @@ -261,7 +241,7 @@ export class WarmPhase extends PureComponent {
- {hotPhaseReplicaCount > 1 ? ( + {hotPhasePrimaryShardCount > 1 ? ( @@ -270,9 +250,7 @@ export class WarmPhase extends PureComponent { Shrink the index into a new index with fewer primary shards.{' '} - + @@ -286,64 +264,59 @@ export class WarmPhase extends PureComponent { }} label="Shrink index" /> - - ) : null } - - + {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 + + + + - {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.{' '} - + Reduce the number of segments in your shard by merging smaller files and clearing + deleted ones. @@ -370,10 +343,7 @@ export class WarmPhase extends PureComponent { { - await setPhaseData( - PHASE_FORCE_MERGE_SEGMENTS, - e.target.value - ); + await setPhaseData(PHASE_FORCE_MERGE_SEGMENTS, e.target.value); validate(); }} min={1} 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 fcbdb66909fc9..45202099dedf8 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 @@ -37,6 +37,7 @@ import { phaseToES, getSelectedPolicyName, getSelectedIndexTemplateName, + getFullSelectedIndexTemplate, isNumber, getSelectedPrimaryShardCount, getSelectedReplicaCount, @@ -47,7 +48,7 @@ import { getAliasName, } from '.'; -export const validatePhase = (type, phase) => { +export const validatePhase = (type, phase, state) => { const errors = {}; if (!phase[PHASE_ENABLED]) { @@ -87,11 +88,15 @@ export const validatePhase = (type, phase) => { } if (phase[PHASE_SHRINK_ENABLED]) { - 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.']; + 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.']; + } } } @@ -110,7 +115,6 @@ export const validatePhase = (type, phase) => { 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 @@ -173,7 +177,7 @@ export const validateLifecycle = state => { }; errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_WARM] = { ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_WARM], - ...validatePhase(PHASE_WARM, warmPhase) + ...validatePhase(PHASE_WARM, warmPhase, state) }; errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_COLD] = { ...errors[STRUCTURE_POLICY_CONFIGURATION][PHASE_COLD], From 33df733e6d3de7fa0483e0511128a0b27187321b Mon Sep 17 00:00:00 2001 From: Bill McConaghy Date: Thu, 6 Sep 2018 09:53:10 -0400 Subject: [PATCH 62/62] fixing issue with editing existing policy and saveAsNew --- .../public/store/selectors/policies.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 3b7733e6c4fd0..665264d679ade 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 @@ -171,7 +171,9 @@ export const policyFromES = ({ name, type, phases }) => { [PHASE_WARM]: phaseFromES(phases[PHASE_WARM], PHASE_WARM, defaultWarmPhase), [PHASE_COLD]: phaseFromES(phases[PHASE_COLD], PHASE_COLD, defaultColdPhase), [PHASE_DELETE]: phaseFromES(phases[PHASE_DELETE], PHASE_DELETE, defaultDeletePhase) - } + }, + isNew: false, + saveAsNew: false }; };