From 69234d4dcdfeb71b009d14cc00c1a384d25419e9 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 28 Oct 2020 17:10:49 +0100 Subject: [PATCH] [ILM] Migrate Cold phase to Form Lib (#81754) * use form lib fields and start updating deserializer * delete legacy data tier allocation field * finished deserialization * delete legacy serialization, validation and deserialization * fix type issue and remove propertyOf for now * fix legacy tests and create another number validator * added serialization test coverage * fix https://github.com/elastic/kibana/issues/81697 * clean up remaining legacy tests and slight update to existing test * remove legacy unused components * fix copy to be clearer for more scenarios * remove remaining coldphase interface use and clean up unused i18n * update default index priority for cold phase * updated cold phase index priority to 0 Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../edit_policy/constants.ts | 25 ++ .../edit_policy/edit_policy.helpers.tsx | 22 +- .../edit_policy/edit_policy.test.ts | 184 +++++++++++--- .../client_integration/helpers/index.ts | 1 + .../__jest__/components/edit_policy.test.tsx | 47 ++-- .../common/types/policies.ts | 9 - .../public/application/constants/policy.ts | 13 +- .../cloud_data_tier_callout.tsx | 54 ---- .../data_tier_allocation.scss | 9 - .../data_tier_allocation.tsx | 184 -------------- .../default_allocation_notice.tsx | 106 -------- .../components/data_tier_allocation/index.ts | 13 - .../no_node_attributes_warning.tsx | 50 ---- .../data_tier_allocation/node_allocation.tsx | 121 --------- .../node_attrs_details.tsx | 106 -------- .../node_data_provider.tsx | 70 ------ .../components/data_tier_allocation/types.ts | 28 --- .../components/forcemerge_legacy.tsx | 131 ---------- .../sections/edit_policy/components/index.ts | 9 - .../components/phases/cold_phase.tsx | 233 ------------------ .../phases/cold_phase/cold_phase.tsx | 187 ++++++++++++++ .../components/phases/cold_phase}/index.ts | 2 +- .../components/no_node_attributes_warning.tsx | 4 +- .../data_tier_allocation_legacy_field.tsx | 141 ----------- .../components/phases/shared/index.ts | 2 - .../phases/warm_phase/warm_phase.tsx | 15 +- .../components/policy_json_flyout.tsx | 1 + .../components/set_priority_input_legacy.tsx | 85 ------- .../sections/edit_policy/deserializer.ts | 39 ++- .../sections/edit_policy/edit_policy.tsx | 14 +- .../sections/edit_policy/form_schema.ts | 75 +++++- .../sections/edit_policy/form_validations.ts | 38 ++- .../sections/edit_policy/serializer.ts | 36 +++ .../application/sections/edit_policy/types.ts | 22 +- .../services/policies/cold_phase.ts | 154 ------------ .../policies/policy_serialization.test.ts | 123 +-------- .../services/policies/policy_serialization.ts | 13 +- .../services/policies/policy_validation.ts | 14 +- .../shared/serialize_phase_with_allocation.ts | 42 ---- .../application/services/ui_metric.test.ts | 5 +- .../public/application/services/ui_metric.ts | 4 +- .../translations/translations/ja-JP.json | 3 - .../translations/translations/zh-CN.json | 3 - 43 files changed, 614 insertions(+), 1823 deletions(-) delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/cloud_data_tier_callout.tsx delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.scss delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.tsx delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/default_allocation_notice.tsx delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/index.ts delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/no_node_attributes_warning.tsx delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_allocation.tsx delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_attrs_details.tsx delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_data_provider.tsx delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/types.ts delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/forcemerge_legacy.tsx delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase.tsx create mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx rename x-pack/plugins/index_lifecycle_management/public/application/{services/policies/shared => sections/edit_policy/components/phases/cold_phase}/index.ts (74%) delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_legacy_field.tsx delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input_legacy.tsx delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/services/policies/cold_phase.ts delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/serialize_phase_with_allocation.ts diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts index 0a96146339a58b..3d430cf31621e9 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/constants.ts @@ -30,6 +30,31 @@ export const DEFAULT_POLICY: PolicyFromES = { name: 'my_policy', }; +export const POLICY_WITH_MIGRATE_OFF: PolicyFromES = { + version: 1, + modified_date: Date.now().toString(), + policy: { + name: 'my_policy', + phases: { + hot: { + min_age: '0ms', + actions: { + rollover: { + max_age: '30d', + max_size: '50gb', + }, + }, + }, + warm: { + actions: { + migrate: { enabled: false }, + }, + }, + }, + }, + name: 'my_policy', +}; + export const POLICY_WITH_INCLUDE_EXCLUDE: PolicyFromES = { version: 1, modified_date: Date.now().toString(), diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx index 1716f124b0c83a..ad61641ea1e36a 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx @@ -154,12 +154,12 @@ export const setup = async () => { component.update(); }; - const setSelectedNodeAttribute = (phase: string) => + const setSelectedNodeAttribute = (phase: Phases) => createFormSetValueAction(`${phase}-selectedNodeAttrs`); - const setReplicas = async (value: string) => { - await createFormToggleAction('warm-setReplicasSwitch')(true); - await createFormSetValueAction('warm-selectedReplicaCount')(value); + const setReplicas = (phase: Phases) => async (value: string) => { + await createFormToggleAction(`${phase}-setReplicasSwitch`)(true); + await createFormSetValueAction(`${phase}-selectedReplicaCount`)(value); }; const setShrink = async (value: string) => { @@ -167,6 +167,8 @@ export const setup = async () => { await createFormSetValueAction('warm-selectedPrimaryShardCount')(value); }; + const setFreeze = createFormToggleAction('freezeSwitch'); + return { ...testBed, actions: { @@ -189,13 +191,23 @@ export const setup = async () => { setMinAgeUnits: setMinAgeUnits('warm'), setDataAllocation: setDataAllocation('warm'), setSelectedNodeAttribute: setSelectedNodeAttribute('warm'), - setReplicas, + setReplicas: setReplicas('warm'), setShrink, toggleForceMerge: toggleForceMerge('warm'), setForcemergeSegments: setForcemergeSegmentsCount('warm'), setBestCompression: setBestCompression('warm'), setIndexPriority: setIndexPriority('warm'), }, + cold: { + enable: enable('cold'), + setMinAgeValue: setMinAgeValue('cold'), + setMinAgeUnits: setMinAgeUnits('cold'), + setDataAllocation: setDataAllocation('cold'), + setSelectedNodeAttribute: setSelectedNodeAttribute('cold'), + setReplicas: setReplicas('cold'), + setFreeze, + setIndexPriority: setIndexPriority('cold'), + }, }, }; }; diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts index fccffde3f793f2..11fadf51f27f8d 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.test.ts @@ -15,6 +15,7 @@ import { NEW_SNAPSHOT_POLICY_NAME, SNAPSHOT_POLICY_NAME, DEFAULT_POLICY, + POLICY_WITH_MIGRATE_OFF, POLICY_WITH_INCLUDE_EXCLUDE, POLICY_WITH_NODE_ATTR_AND_OFF_ALLOCATION, POLICY_WITH_NODE_ROLE_ALLOCATION, @@ -199,26 +200,6 @@ describe('', () => { `); }); - test('default allocation with replicas set', async () => { - const { actions } = testBed; - await actions.warm.enable(true); - await actions.warm.setReplicas('123'); - await actions.savePolicy(); - const latestRequest = server.requests[server.requests.length - 1]; - const warmPhaseActions = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm - .actions; - expect(warmPhaseActions).toMatchInlineSnapshot(` - Object { - "allocate": Object { - "number_of_replicas": 123, - }, - "set_priority": Object { - "priority": 50, - }, - } - `); - }); - test('setting warm phase on rollover to "true"', async () => { const { actions } = testBed; await actions.warm.enable(true); @@ -252,6 +233,7 @@ describe('', () => { test('preserves include, exclude allocation settings', async () => { const { actions } = testBed; await actions.warm.setDataAllocation('node_attrs'); + await actions.warm.setSelectedNodeAttribute('test:123'); await actions.savePolicy(); const latestRequest = server.requests[server.requests.length - 1]; const warmPhaseAllocate = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm @@ -264,6 +246,101 @@ describe('', () => { "include": Object { "abc": "123", }, + "require": Object { + "test": "123", + }, + } + `); + }); + }); + }); + + describe('cold phase', () => { + describe('serialization', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadPolicies([DEFAULT_POLICY]); + httpRequestsMockHelpers.setListNodes({ + nodesByRoles: {}, + nodesByAttributes: { test: ['123'] }, + isUsingDeprecatedDataRoleConfig: false, + }); + httpRequestsMockHelpers.setLoadSnapshotPolicies([]); + + await act(async () => { + testBed = await setup(); + }); + + const { component } = testBed; + component.update(); + }); + + test('default values', async () => { + const { actions } = testBed; + + await actions.cold.enable(true); + await actions.savePolicy(); + const latestRequest = server.requests[server.requests.length - 1]; + const entirePolicy = JSON.parse(JSON.parse(latestRequest.requestBody).body); + expect(entirePolicy.phases.cold).toMatchInlineSnapshot(` + Object { + "actions": Object { + "set_priority": Object { + "priority": 0, + }, + }, + "min_age": "0d", + } + `); + }); + + test('setting all values', async () => { + const { actions } = testBed; + + await actions.cold.enable(true); + await actions.cold.setMinAgeValue('123'); + await actions.cold.setMinAgeUnits('s'); + await actions.cold.setDataAllocation('node_attrs'); + await actions.cold.setSelectedNodeAttribute('test:123'); + await actions.cold.setReplicas('123'); + await actions.cold.setFreeze(true); + await actions.cold.setIndexPriority('123'); + + await actions.savePolicy(); + const latestRequest = server.requests[server.requests.length - 1]; + const entirePolicy = JSON.parse(JSON.parse(latestRequest.requestBody).body); + + expect(entirePolicy).toMatchInlineSnapshot(` + Object { + "name": "my_policy", + "phases": Object { + "cold": Object { + "actions": Object { + "allocate": Object { + "number_of_replicas": 123, + "require": Object { + "test": "123", + }, + }, + "freeze": Object {}, + "set_priority": Object { + "priority": 123, + }, + }, + "min_age": "123s", + }, + "hot": Object { + "actions": Object { + "rollover": Object { + "max_age": "30d", + "max_size": "50gb", + }, + "set_priority": Object { + "priority": 100, + }, + }, + "min_age": "0ms", + }, + }, } `); }); @@ -385,6 +462,33 @@ describe('', () => { }); describe('data allocation', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadPolicies([POLICY_WITH_MIGRATE_OFF]); + httpRequestsMockHelpers.setListNodes({ + nodesByRoles: {}, + nodesByAttributes: { test: ['123'] }, + isUsingDeprecatedDataRoleConfig: false, + }); + httpRequestsMockHelpers.setLoadSnapshotPolicies([]); + + await act(async () => { + testBed = await setup(); + }); + + const { component } = testBed; + component.update(); + }); + + test('setting node_attr based allocation, but not selecting node attribute', async () => { + const { actions } = testBed; + await actions.warm.setDataAllocation('node_attrs'); + await actions.savePolicy(); + const latestRequest = server.requests[server.requests.length - 1]; + const warmPhase = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm; + + expect(warmPhase.actions.migrate).toEqual({ enabled: false }); + }); + describe('node roles', () => { beforeEach(async () => { httpRequestsMockHelpers.setLoadPolicies([POLICY_WITH_NODE_ROLE_ALLOCATION]); @@ -401,15 +505,32 @@ describe('', () => { const { component } = testBed; component.update(); }); - test('showing "default" type', () => { + + test('detecting use of the recommended allocation type', () => { const { find } = testBed; - expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).toContain( - 'recommended' - ); - expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).not.toContain( - 'Custom' - ); - expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).not.toContain('Off'); + const selectedDataAllocation = find( + 'warm-dataTierAllocationControls.dataTierSelect' + ).text(); + expect(selectedDataAllocation).toBe('Use warm nodes (recommended)'); + }); + + test('setting replicas serialization', async () => { + const { actions } = testBed; + await actions.warm.setReplicas('123'); + await actions.savePolicy(); + const latestRequest = server.requests[server.requests.length - 1]; + const warmPhaseActions = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm + .actions; + expect(warmPhaseActions).toMatchInlineSnapshot(` + Object { + "allocate": Object { + "number_of_replicas": 123, + }, + "set_priority": Object { + "priority": 50, + }, + } + `); }); }); describe('node attr and none', () => { @@ -429,9 +550,12 @@ describe('', () => { component.update(); }); - test('showing "custom" and "off" types', () => { + test('detecting use of the custom allocation type', () => { + const { find } = testBed; + expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).toBe('Custom'); + }); + test('detecting use of the "off" allocation type', () => { const { find } = testBed; - expect(find('warm-dataTierAllocationControls.dataTierSelect').text()).toContain('Custom'); expect(find('cold-dataTierAllocationControls.dataTierSelect').text()).toContain('Off'); }); }); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts index c6d27ca890b54f..e8ebc2963d16a5 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/index.ts @@ -17,4 +17,5 @@ export type TestSubjects = | 'hot-selectedMaxDocuments' | 'hot-selectedMaxAge' | 'hot-selectedMaxAgeUnits' + | 'freezeSwitch' | string; diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx index 4ba6cee7b027f3..4a3fedfb264ac1 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx +++ b/x-pack/plugins/index_lifecycle_management/__jest__/components/edit_policy.test.tsx @@ -119,9 +119,6 @@ const noRollover = async (rendered: ReactWrapper) => { }); rendered.update(); }; -const getNodeAttributeSelectLegacy = (rendered: ReactWrapper, phase: string) => { - return rendered.find(`select#${phase}-selectedNodeAttrs`); -}; const getNodeAttributeSelect = (rendered: ReactWrapper, phase: string) => { return findTestSubject(rendered, `${phase}-selectedNodeAttrs`); }; @@ -142,15 +139,6 @@ const setPhaseAfter = async (rendered: ReactWrapper, phase: string, after: strin }); rendered.update(); }; -const setPhaseIndexPriorityLegacy = ( - rendered: ReactWrapper, - phase: string, - priority: string | number -) => { - const priorityInput = rendered.find(`input#${phase}-phaseIndexPriority`); - priorityInput.simulate('change', { target: { value: priority } }); - rendered.update(); -}; const setPhaseIndexPriority = async ( rendered: ReactWrapper, phase: string, @@ -184,7 +172,7 @@ describe('edit policy', () => { */ const waitForFormLibValidation = (rendered: ReactWrapper) => { act(() => { - jest.advanceTimersByTime(1000); + jest.runAllTimers(); }); rendered.update(); }; @@ -394,7 +382,7 @@ describe('edit policy', () => { setPolicyName(rendered, 'mypolicy'); await setPhaseIndexPriority(rendered, 'hot', '-1'); waitForFormLibValidation(rendered); - expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.numberGreatThan0Required]); + expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]); }); }); describe('warm phase', () => { @@ -519,7 +507,7 @@ describe('edit policy', () => { await activatePhase(rendered, 'warm'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeTruthy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy(); - expect(getNodeAttributeSelectLegacy(rendered, 'warm').exists()).toBeFalsy(); + expect(getNodeAttributeSelect(rendered, 'warm').exists()).toBeFalsy(); }); test('should show warning instead of node attributes input when none exist', async () => { http.setupNodeListResponse({ @@ -534,7 +522,7 @@ describe('edit policy', () => { expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'warm'); expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeTruthy(); - expect(getNodeAttributeSelectLegacy(rendered, 'warm').exists()).toBeFalsy(); + expect(getNodeAttributeSelect(rendered, 'warm').exists()).toBeFalsy(); }); test('should show node attributes input when attributes exist', async () => { const rendered = mountWithIntl(component); @@ -625,8 +613,9 @@ describe('edit policy', () => { await noRollover(rendered); setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); - setPhaseAfterLegacy(rendered, 'cold', '0'); - await save(rendered); + await setPhaseAfter(rendered, 'cold', '0'); + waitForFormLibValidation(rendered); + rendered.update(); expectedErrorMessages(rendered, []); }); test('should show positive number required error when trying to save cold phase with -1 for after', async () => { @@ -634,9 +623,9 @@ describe('edit policy', () => { await noRollover(rendered); setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); - setPhaseAfterLegacy(rendered, 'cold', '-1'); - await save(rendered); - expectedErrorMessages(rendered, [positiveNumberRequiredMessage]); + await setPhaseAfter(rendered, 'cold', '-1'); + waitForFormLibValidation(rendered); + expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]); }); test('should show spinner for node attributes input when loading', async () => { server.respondImmediately = false; @@ -646,7 +635,7 @@ describe('edit policy', () => { await activatePhase(rendered, 'cold'); expect(rendered.find('.euiLoadingSpinner').exists()).toBeTruthy(); expect(rendered.find('.euiCallOut--warning').exists()).toBeFalsy(); - expect(getNodeAttributeSelectLegacy(rendered, 'cold').exists()).toBeFalsy(); + expect(getNodeAttributeSelect(rendered, 'cold').exists()).toBeFalsy(); }); test('should show warning instead of node attributes input when none exist', async () => { http.setupNodeListResponse({ @@ -661,7 +650,7 @@ describe('edit policy', () => { expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'cold'); expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeTruthy(); - expect(getNodeAttributeSelectLegacy(rendered, 'cold').exists()).toBeFalsy(); + expect(getNodeAttributeSelect(rendered, 'cold').exists()).toBeFalsy(); }); test('should show node attributes input when attributes exist', async () => { const rendered = mountWithIntl(component); @@ -671,7 +660,7 @@ describe('edit policy', () => { expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'cold'); expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeFalsy(); - const nodeAttributesSelect = getNodeAttributeSelectLegacy(rendered, 'cold'); + const nodeAttributesSelect = getNodeAttributeSelect(rendered, 'cold'); expect(nodeAttributesSelect.exists()).toBeTruthy(); expect(nodeAttributesSelect.find('option').length).toBe(2); }); @@ -683,7 +672,7 @@ describe('edit policy', () => { expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy(); await openNodeAttributesSection(rendered, 'cold'); expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeFalsy(); - const nodeAttributesSelect = getNodeAttributeSelectLegacy(rendered, 'cold'); + const nodeAttributesSelect = getNodeAttributeSelect(rendered, 'cold'); expect(nodeAttributesSelect.exists()).toBeTruthy(); expect(findTestSubject(rendered, 'cold-viewNodeDetailsFlyoutButton').exists()).toBeFalsy(); expect(nodeAttributesSelect.find('option').length).toBe(2); @@ -702,10 +691,10 @@ describe('edit policy', () => { await noRollover(rendered); setPolicyName(rendered, 'mypolicy'); await activatePhase(rendered, 'cold'); - setPhaseAfterLegacy(rendered, 'cold', '1'); - setPhaseIndexPriorityLegacy(rendered, 'cold', '-1'); - await save(rendered); - expectedErrorMessages(rendered, [positiveNumberRequiredMessage]); + await setPhaseAfter(rendered, 'cold', '1'); + await setPhaseIndexPriority(rendered, 'cold', '-1'); + waitForFormLibValidation(rendered); + expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]); }); test('should show default allocation warning when no node roles are found', async () => { http.setupNodeListResponse({ diff --git a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts index 813fcd9c253f1f..5692decbbf7a88 100644 --- a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts +++ b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts @@ -116,7 +116,6 @@ export interface ForcemergeAction { export interface LegacyPolicy { name: string; phases: { - cold: ColdPhase; delete: DeletePhase; }; } @@ -159,14 +158,6 @@ export interface PhaseWithForcemergeAction { bestCompressionEnabled: boolean; } -export interface ColdPhase - extends CommonPhaseSettings, - PhaseWithMinAge, - PhaseWithAllocationAction, - PhaseWithIndexPriority { - freezeEnabled: boolean; -} - export interface DeletePhase extends CommonPhaseSettings, PhaseWithMinAge { waitForSnapshotPolicy: string; } diff --git a/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts b/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts index 136b68727672aa..23d7387aa70763 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/constants/policy.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { SerializedPhase, ColdPhase, DeletePhase, SerializedPolicy } from '../../../common/types'; +import { SerializedPhase, DeletePhase, SerializedPolicy } from '../../../common/types'; export const defaultSetPriority: string = '100'; @@ -24,17 +24,6 @@ export const defaultPolicy: SerializedPolicy = { }, }; -export const defaultNewColdPhase: ColdPhase = { - phaseEnabled: false, - selectedMinimumAge: '0', - selectedMinimumAgeUnits: 'd', - selectedNodeAttrs: '', - selectedReplicaCount: '', - freezeEnabled: false, - phaseIndexPriority: '0', - dataTierAllocationType: 'default', -}; - export const defaultNewDeletePhase: DeletePhase = { phaseEnabled: false, selectedMinimumAge: '0', diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/cloud_data_tier_callout.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/cloud_data_tier_callout.tsx deleted file mode 100644 index fc87b553ba5214..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/cloud_data_tier_callout.tsx +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import React, { FunctionComponent } from 'react'; -import { EuiCallOut, EuiLink } from '@elastic/eui'; - -import { useKibana } from '../../../../../shared_imports'; - -const deployment = i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.body.elasticDeploymentLink', - { - defaultMessage: 'deployment', - } -); - -const i18nTexts = { - title: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.coldTierTitle', { - defaultMessage: 'Create a cold tier', - }), - body: (deploymentUrl?: string) => { - return ( - - {deployment} - - ) : ( - deployment - ), - }} - /> - ); - }, -}; - -export const CloudDataTierCallout: FunctionComponent = () => { - const { - services: { cloud }, - } = useKibana(); - - return ( - - {i18nTexts.body(cloud?.cloudDeploymentUrl)} - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.scss b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.scss deleted file mode 100644 index 62ec3f303e1e8c..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.scss +++ /dev/null @@ -1,9 +0,0 @@ -.indexLifecycleManagement__phase__dataTierAllocation { - &__controlSection { - background-color: $euiColorLightestShade; - padding-top: $euiSizeM; - padding-left: $euiSizeM; - padding-right: $euiSizeM; - padding-bottom: $euiSizeM; - } -} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.tsx deleted file mode 100644 index f58f36fc45a0cb..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/data_tier_allocation.tsx +++ /dev/null @@ -1,184 +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, { FunctionComponent, useEffect } from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiText, EuiFormRow, EuiSpacer, EuiSuperSelect, EuiSuperSelectOption } from '@elastic/eui'; - -import { DataTierAllocationType } from '../../../../../../common/types'; -import { NodeAllocation } from './node_allocation'; -import { SharedProps } from './types'; - -import './data_tier_allocation.scss'; - -type SelectOptions = EuiSuperSelectOption; - -const i18nTexts = { - allocationFieldLabel: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.allocationFieldLabel', - { defaultMessage: 'Data tier options' } - ), - allocationOptions: { - warm: { - default: { - input: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.defaultOption.input', - { defaultMessage: 'Use warm nodes (recommended)' } - ), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.defaultOption.helpText', - { defaultMessage: 'Move data to nodes in the warm tier.' } - ), - }, - none: { - inputDisplay: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.noneOption.input', - { defaultMessage: 'Off' } - ), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.noneOption.helpText', - { defaultMessage: 'Do not move data in the warm phase.' } - ), - }, - custom: { - inputDisplay: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.customOption.input', - { defaultMessage: 'Custom' } - ), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.warm.customOption.helpText', - { defaultMessage: 'Move data based on node attributes.' } - ), - }, - }, - cold: { - default: { - input: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.input', - { defaultMessage: 'Use cold nodes (recommended)' } - ), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.helpText', - { defaultMessage: 'Move data to nodes in the cold tier.' } - ), - }, - none: { - inputDisplay: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.noneOption.input', - { defaultMessage: 'Off' } - ), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.noneOption.helpText', - { defaultMessage: 'Do not move data in the cold phase.' } - ), - }, - custom: { - inputDisplay: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.input', - { defaultMessage: 'Custom' } - ), - helpText: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.helpText', - { defaultMessage: 'Move data based on node attributes.' } - ), - }, - }, - }, -}; - -export const DataTierAllocation: FunctionComponent = (props) => { - const { phaseData, setPhaseData, phase, hasNodeAttributes, disableDataTierOption } = props; - - useEffect(() => { - if (disableDataTierOption && phaseData.dataTierAllocationType === 'default') { - /** - * @TODO - * This is a slight hack because we only know we should disable the "default" option further - * down the component tree (i.e., after the policy has been deserialized). - * - * We reset the value to "custom" if we deserialized to "default". - * - * It would be better if we had all the information we needed before deserializing and - * were able to handle this at the deserialization step instead of patching further down - * the component tree - this should be a future refactor. - */ - setPhaseData('dataTierAllocationType', 'custom'); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return ( -
- - setPhaseData('dataTierAllocationType', value)} - options={ - [ - disableDataTierOption - ? undefined - : { - 'data-test-subj': 'defaultDataAllocationOption', - value: 'default', - inputDisplay: i18nTexts.allocationOptions[phase].default.input, - dropdownDisplay: ( - <> - {i18nTexts.allocationOptions[phase].default.input} - -

- {i18nTexts.allocationOptions[phase].default.helpText} -

-
- - ), - }, - { - 'data-test-subj': 'customDataAllocationOption', - value: 'custom', - inputDisplay: i18nTexts.allocationOptions[phase].custom.inputDisplay, - dropdownDisplay: ( - <> - {i18nTexts.allocationOptions[phase].custom.inputDisplay} - -

- {i18nTexts.allocationOptions[phase].custom.helpText} -

-
- - ), - }, - { - 'data-test-subj': 'noneDataAllocationOption', - value: 'none', - inputDisplay: i18nTexts.allocationOptions[phase].none.inputDisplay, - dropdownDisplay: ( - <> - {i18nTexts.allocationOptions[phase].none.inputDisplay} - -

- {i18nTexts.allocationOptions[phase].none.helpText} -

-
- - ), - }, - ].filter(Boolean) as SelectOptions[] - } - /> -
- {phaseData.dataTierAllocationType === 'custom' && hasNodeAttributes && ( - <> - -
- -
- - )} -
- ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/default_allocation_notice.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/default_allocation_notice.tsx deleted file mode 100644 index 3d0052c69607b4..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/default_allocation_notice.tsx +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import { i18n } from '@kbn/i18n'; -import React, { FunctionComponent } from 'react'; -import { EuiCallOut } from '@elastic/eui'; - -import { PhaseWithAllocation, DataTierRole } from '../../../../../../common/types'; - -import { AllocationNodeRole } from '../../../../lib'; - -const i18nTextsNodeRoleToDataTier: Record = { - data_hot: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.dataTierHotLabel', { - defaultMessage: 'hot', - }), - data_warm: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.dataTierWarmLabel', { - defaultMessage: 'warm', - }), - data_cold: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.dataTierColdLabel', { - defaultMessage: 'cold', - }), -}; - -const i18nTexts = { - notice: { - warm: { - title: i18n.translate( - 'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm.title', - { defaultMessage: 'No nodes assigned to the warm tier' } - ), - body: (nodeRole: DataTierRole) => - i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm', { - defaultMessage: - 'This policy will move data in the warm phase to {tier} tier nodes instead.', - values: { tier: i18nTextsNodeRoleToDataTier[nodeRole] }, - }), - }, - cold: { - title: i18n.translate( - 'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold.title', - { defaultMessage: 'No nodes assigned to the cold tier' } - ), - body: (nodeRole: DataTierRole) => - i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold', { - defaultMessage: - 'This policy will move data in the cold phase to {tier} tier nodes instead.', - values: { tier: i18nTextsNodeRoleToDataTier[nodeRole] }, - }), - }, - }, - warning: { - warm: { - title: i18n.translate( - 'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableTitle', - { defaultMessage: 'No nodes assigned to the warm tier' } - ), - body: i18n.translate( - 'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableBody', - { - defaultMessage: - 'Assign at least one node to the warm or hot tier to use role-based allocation. The policy will fail to complete allocation if there are no available nodes.', - } - ), - }, - cold: { - title: i18n.translate( - 'xpack.indexLifecycleMgmt.coldPhase.dataTier.defaultAllocationNotAvailableTitle', - { defaultMessage: 'No nodes assigned to the cold tier' } - ), - body: i18n.translate( - 'xpack.indexLifecycleMgmt.coldPhase.dataTier.defaultAllocationNotAvailableBody', - { - defaultMessage: - 'Assign at least one node to the cold, warm, or hot tier to use role-based allocation. The policy will fail to complete allocation if there are no available nodes.', - } - ), - }, - }, -}; - -interface Props { - phase: PhaseWithAllocation; - targetNodeRole: AllocationNodeRole; -} - -export const DefaultAllocationNotice: FunctionComponent = ({ phase, targetNodeRole }) => { - const content = - targetNodeRole === 'none' ? ( - - {i18nTexts.warning[phase].body} - - ) : ( - - {i18nTexts.notice[phase].body(targetNodeRole)} - - ); - - return content; -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/index.ts deleted file mode 100644 index 937e3dd28da973..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/index.ts +++ /dev/null @@ -1,13 +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 { NodesDataProvider } from './node_data_provider'; -export { NodeAllocation } from './node_allocation'; -export { NodeAttrsDetails } from './node_attrs_details'; -export { DataTierAllocation } from './data_tier_allocation'; -export { DefaultAllocationNotice } from './default_allocation_notice'; -export { NoNodeAttributesWarning } from './no_node_attributes_warning'; -export { CloudDataTierCallout } from './cloud_data_tier_callout'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/no_node_attributes_warning.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/no_node_attributes_warning.tsx deleted file mode 100644 index 69185277f64ce6..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/no_node_attributes_warning.tsx +++ /dev/null @@ -1,50 +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, { FunctionComponent } from 'react'; -import { EuiCallOut } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { PhaseWithAllocation } from '../../../../../../common/types'; - -const i18nTexts = { - title: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingLabel', { - defaultMessage: 'No custom node attributes configured', - }), - warm: { - body: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.warm.nodeAttributesMissingDescription', - { - defaultMessage: - 'Define custom node attributes in elasticsearch.yml to use attribute-based allocation. Warm nodes will be used instead.', - } - ), - }, - cold: { - body: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.cold.nodeAttributesMissingDescription', - { - defaultMessage: - 'Define custom node attributes in elasticsearch.yml to use attribute-based allocation. Cold nodes will be used instead.', - } - ), - }, -}; - -export const NoNodeAttributesWarning: FunctionComponent<{ phase: PhaseWithAllocation }> = ({ - phase, -}) => { - return ( - - {i18nTexts[phase].body} - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_allocation.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_allocation.tsx deleted file mode 100644 index a57a6ba4ff2c65..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_allocation.tsx +++ /dev/null @@ -1,121 +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, { useState, FunctionComponent } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; -import { EuiSelect, EuiButtonEmpty, EuiText, EuiSpacer } from '@elastic/eui'; - -import { PhaseWithAllocationAction } from '../../../../../../common/types'; -import { propertyof } from '../../../../services/policies/policy_validation'; - -import { ErrableFormRow } from '../form_errors'; - -import { NodeAttrsDetails } from './node_attrs_details'; -import { SharedProps } from './types'; -import { LearnMoreLink } from '../learn_more_link'; - -const learnMoreLink = ( - - } - docPath="modules-cluster.html#cluster-shard-allocation-settings" - /> -); - -const i18nTexts = { - doNotModifyAllocationOption: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption', - { defaultMessage: 'Do not modify allocation configuration' } - ), -}; - -export const NodeAllocation: FunctionComponent = ({ - phase, - setPhaseData, - errors, - phaseData, - isShowingErrors, - nodes, -}) => { - const [selectedNodeAttrsForDetails, setSelectedNodeAttrsForDetails] = useState( - null - ); - - const nodeOptions = Object.keys(nodes).map((attrs) => ({ - text: `${attrs} (${nodes[attrs].length})`, - value: attrs, - })); - - nodeOptions.sort((a, b) => a.value.localeCompare(b.value)); - - // check that this string is a valid property - const nodeAttrsProperty = propertyof('selectedNodeAttrs'); - - return ( - <> - -

- -

-
- - - {/* - TODO: this field component must be revisited to support setting multiple require values and to support - setting `include and exclude values on ILM policies. See https://github.com/elastic/kibana/issues/77344 - */} - setSelectedNodeAttrsForDetails(phaseData.selectedNodeAttrs)} - > - - - ) : null - } - > - { - setPhaseData(nodeAttrsProperty, e.target.value); - }} - /> - - - {selectedNodeAttrsForDetails ? ( - setSelectedNodeAttrsForDetails(null)} - /> - ) : null} - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_attrs_details.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_attrs_details.tsx deleted file mode 100644 index c29495d13eb8ed..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_attrs_details.tsx +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { - EuiFlyoutBody, - EuiFlyout, - EuiTitle, - EuiInMemoryTable, - EuiSpacer, - EuiPortal, - EuiLoadingContent, - EuiCallOut, - EuiButton, -} from '@elastic/eui'; - -import { useLoadNodeDetails } from '../../../../services/api'; - -interface Props { - close: () => void; - selectedNodeAttrs: string; -} - -export const NodeAttrsDetails: React.FunctionComponent = ({ close, selectedNodeAttrs }) => { - const { data, isLoading, error, resendRequest } = useLoadNodeDetails(selectedNodeAttrs); - let content; - if (isLoading) { - content = ; - } else if (error) { - const { statusCode, message } = error; - content = ( - - } - color="danger" - > -

- {message} ({statusCode}) -

- - - -
- ); - } else { - content = ( - - ); - } - return ( - - - - -

- -

-
- - {content} -
-
-
- ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_data_provider.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_data_provider.tsx deleted file mode 100644 index a7c0f3ec7c8660..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/node_data_provider.tsx +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import React from 'react'; -import { EuiButton, EuiCallOut, EuiLoadingSpinner, EuiSpacer } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { ListNodesRouteResponse } from '../../../../../../common/types'; -import { useLoadNodes } from '../../../../services/api'; - -interface Props { - children: (data: ListNodesRouteResponse) => JSX.Element; -} - -export const NodesDataProvider = ({ children }: Props): JSX.Element => { - const { isLoading, data, error, resendRequest } = useLoadNodes(); - - if (isLoading) { - return ( - <> - - - - ); - } - - const renderError = () => { - if (error) { - const { statusCode, message } = error; - return ( - <> - - } - color="danger" - > -

- {message} ({statusCode}) -

- - - -
- - - - ); - } - return null; - }; - - return ( - <> - {renderError()} - {/* `data` will always be defined because we use an initial value when loading */} - {children(data!)} - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/types.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/types.ts deleted file mode 100644 index d3dd536d97df00..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/data_tier_allocation/types.ts +++ /dev/null @@ -1,28 +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 { - ListNodesRouteResponse, - PhaseWithAllocation, - PhaseWithAllocationAction, -} from '../../../../../../common/types'; -import { PhaseValidationErrors } from '../../../../services/policies/policy_validation'; - -export interface SharedProps { - phase: PhaseWithAllocation; - errors?: PhaseValidationErrors; - phaseData: PhaseWithAllocationAction; - setPhaseData: (dataKey: keyof PhaseWithAllocationAction, value: string) => void; - isShowingErrors: boolean; - nodes: ListNodesRouteResponse['nodesByAttributes']; - hasNodeAttributes: boolean; - /** - * When on Cloud we want to disable the data tier allocation option when we detect that we are not - * using node roles in our Node config yet. See {@link ListNodesRouteResponse} for information about how this is - * detected. - */ - disableDataTierOption: boolean; -} diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/forcemerge_legacy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/forcemerge_legacy.tsx deleted file mode 100644 index 0b0dbe273c0240..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/forcemerge_legacy.tsx +++ /dev/null @@ -1,131 +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. - */ - -/** - * PLEASE NOTE: This component is currently duplicated. A version of this component wired up with - * the form lib lives in ./phases/shared - */ - -import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiDescribedFormGroup, - EuiFieldNumber, - EuiFormRow, - EuiSpacer, - EuiSwitch, - EuiTextColor, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React from 'react'; -import { LearnMoreLink } from './learn_more_link'; -import { ErrableFormRow } from './form_errors'; -import { Phases, PhaseWithForcemergeAction } from '../../../../../common/types'; -import { PhaseValidationErrors } from '../../../services/policies/policy_validation'; - -const forcemergeLabel = i18n.translate('xpack.indexLifecycleMgmt.forcemerge.enableLabel', { - defaultMessage: 'Force merge data', -}); - -const bestCompressionLabel = i18n.translate( - 'xpack.indexLifecycleMgmt.forcemerge.bestCompressionLabel', - { - defaultMessage: 'Compress stored fields', - } -); - -interface Props { - errors?: PhaseValidationErrors; - phase: keyof Phases & string; - phaseData: PhaseWithForcemergeAction; - setPhaseData: (dataKey: keyof PhaseWithForcemergeAction, value: boolean | string) => void; - isShowingErrors: boolean; -} - -export const Forcemerge: React.FunctionComponent = ({ - errors, - phaseData, - phase, - setPhaseData, - isShowingErrors, -}) => { - return ( - - - - } - description={ - - {' '} - - - } - titleSize="xs" - fullWidth - > - { - setPhaseData('forceMergeEnabled', e.target.checked); - }} - aria-controls="forcemergeContent" - /> - - -
- {phaseData.forceMergeEnabled ? ( - <> - - { - setPhaseData('selectedForceMergeSegments', e.target.value); - }} - min={1} - /> - - - } - > - { - setPhaseData('bestCompressionEnabled', e.target.checked); - }} - /> - - - ) : null} -
-
- ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts index 2b774b00b98a9f..a04608338718e3 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/index.ts @@ -11,16 +11,7 @@ export { MinAgeInput } from './min_age_input_legacy'; export { OptionalLabel } from './optional_label'; export { PhaseErrorMessage } from './phase_error_message'; export { PolicyJsonFlyout } from './policy_json_flyout'; -export { SetPriorityInput } from './set_priority_input_legacy'; export { SnapshotPolicies } from './snapshot_policies'; -export { - DataTierAllocation, - NodeAllocation, - NodeAttrsDetails, - NodesDataProvider, - DefaultAllocationNotice, -} from './data_tier_allocation'; export { DescribedFormField } from './described_form_field'; -export { Forcemerge } from './forcemerge_legacy'; export * from './phases'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase.tsx deleted file mode 100644 index da6c358aa67c15..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase.tsx +++ /dev/null @@ -1,233 +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, { FunctionComponent, Fragment } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; -import { get } from 'lodash'; - -import { EuiFieldNumber, EuiDescribedFormGroup, EuiSwitch, EuiTextColor } from '@elastic/eui'; - -import { ColdPhase as ColdPhaseInterface, Phases } from '../../../../../../common/types'; - -import { useFormData } from '../../../../../shared_imports'; - -import { PhaseValidationErrors } from '../../../../services/policies/policy_validation'; - -import { - LearnMoreLink, - ActiveBadge, - PhaseErrorMessage, - OptionalLabel, - ErrableFormRow, - SetPriorityInput, - MinAgeInput, - DescribedFormField, -} from '../'; - -import { DataTierAllocationFieldLegacy, useRolloverPath } from './shared'; - -const i18nTexts = { - freezeLabel: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.freezeIndexLabel', { - defaultMessage: 'Freeze index', - }), - dataTierAllocation: { - description: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.dataTier.description', { - defaultMessage: - 'Move data to nodes optimized for less frequent, read-only access. Store data in the cold phase on less-expensive hardware.', - }), - }, -}; - -const coldProperty: keyof Phases = 'cold'; -const phaseProperty = (propertyName: keyof ColdPhaseInterface) => propertyName; - -interface Props { - setPhaseData: (key: keyof ColdPhaseInterface & string, value: string | boolean) => void; - phaseData: ColdPhaseInterface; - isShowingErrors: boolean; - errors?: PhaseValidationErrors; -} -export const ColdPhase: FunctionComponent = ({ - setPhaseData, - phaseData, - errors, - isShowingErrors, -}) => { - const [formData] = useFormData({ - watch: [useRolloverPath], - }); - - const hotPhaseRolloverEnabled = get(formData, useRolloverPath); - - return ( -
- <> - {/* Section title group; containing min age */} - -

- -

{' '} - {phaseData.phaseEnabled && !isShowingErrors ? : null} - -
- } - titleSize="s" - description={ - -

- -

- - } - id={`${coldProperty}-${phaseProperty('phaseEnabled')}`} - checked={phaseData.phaseEnabled} - onChange={(e) => { - setPhaseData(phaseProperty('phaseEnabled'), e.target.checked); - }} - aria-controls="coldPhaseContent" - /> -
- } - fullWidth - > - {phaseData.phaseEnabled ? ( - - errors={errors} - phaseData={phaseData} - phase={coldProperty} - isShowingErrors={isShowingErrors} - setPhaseData={setPhaseData} - rolloverEnabled={hotPhaseRolloverEnabled} - /> - ) : null} - - {phaseData.phaseEnabled ? ( - - {/* Data tier allocation section */} - - - {/* Replicas section */} - - {i18n.translate('xpack.indexLifecycleMgmt.coldPhase.replicasTitle', { - defaultMessage: 'Replicas', - })} - - } - description={i18n.translate( - 'xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasDescription', - { - defaultMessage: - 'Set the number of replicas. Remains the same as the previous phase by default.', - } - )} - switchProps={{ - label: i18n.translate( - 'xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel', - { defaultMessage: 'Set replicas' } - ), - initialValue: Boolean(phaseData.selectedReplicaCount), - onChange: (v) => { - if (!v) { - setPhaseData('selectedReplicaCount', ''); - } - }, - }} - fullWidth - > - - - - - } - isShowingErrors={isShowingErrors} - errors={errors?.selectedReplicaCount} - > - { - setPhaseData(phaseProperty('selectedReplicaCount'), e.target.value); - }} - min={0} - /> - - - {/* Freeze section */} - - - - } - description={ - - {' '} - - - } - fullWidth - titleSize="xs" - > - { - setPhaseData(phaseProperty('freezeEnabled'), e.target.checked); - }} - label={i18nTexts.freezeLabel} - aria-label={i18nTexts.freezeLabel} - /> - - - errors={errors} - phaseData={phaseData} - phase={coldProperty} - isShowingErrors={isShowingErrors} - setPhaseData={setPhaseData} - /> - - ) : null} - - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx new file mode 100644 index 00000000000000..84e955a91ad7ce --- /dev/null +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx @@ -0,0 +1,187 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * 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, { FunctionComponent } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; +import { get } from 'lodash'; + +import { EuiDescribedFormGroup, EuiTextColor } from '@elastic/eui'; + +import { Phases } from '../../../../../../../common/types'; + +import { + useFormData, + useFormContext, + UseField, + ToggleField, + NumericField, +} from '../../../../../../shared_imports'; + +import { useEditPolicyContext } from '../../../edit_policy_context'; + +import { LearnMoreLink, ActiveBadge, PhaseErrorMessage, DescribedFormField } from '../../'; + +import { MinAgeInputField, DataTierAllocationField, SetPriorityInput } from '../shared'; + +const i18nTexts = { + dataTierAllocation: { + description: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.dataTier.description', { + defaultMessage: + 'Move data to nodes optimized for less frequent, read-only access. Store data in the cold phase on less-expensive hardware.', + }), + }, +}; + +const coldProperty: keyof Phases = 'cold'; + +const formFieldPaths = { + enabled: '_meta.cold.enabled', +}; + +export const ColdPhase: FunctionComponent = () => { + const { originalPolicy } = useEditPolicyContext(); + const form = useFormContext(); + + const [formData] = useFormData({ + watch: [formFieldPaths.enabled], + }); + + const enabled = get(formData, formFieldPaths.enabled); + const isShowingErrors = form.isValid === false; + + return ( +
+ <> + {/* Section title group; containing min age */} + +

+ +

{' '} + {enabled && !isShowingErrors ? : null} + +
+ } + titleSize="s" + description={ + <> +

+ +

+ + + } + fullWidth + > + {enabled && } + + {enabled && ( + <> + {/* Data tier allocation section */} + + + {/* Replicas section */} + + {i18n.translate('xpack.indexLifecycleMgmt.coldPhase.replicasTitle', { + defaultMessage: 'Replicas', + })} + + } + description={i18n.translate( + 'xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasDescription', + { + defaultMessage: + 'Set the number of replicas. Remains the same as the previous phase by default.', + } + )} + switchProps={{ + 'data-test-subj': 'cold-setReplicasSwitch', + label: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel', + { defaultMessage: 'Set replicas' } + ), + initialValue: Boolean( + originalPolicy.phases.cold?.actions?.allocate?.number_of_replicas + ), + }} + fullWidth + > + + + {/* Freeze section */} + + + + } + description={ + + {' '} + + + } + fullWidth + titleSize="xs" + > + + + + + )} + + + ); +}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/index.ts similarity index 74% rename from x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/index.ts rename to x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/index.ts index fe97b85778a53f..df79607f33dbcc 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { serializePhaseWithAllocation } from './serialize_phase_with_allocation'; +export { ColdPhase } from './cold_phase'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx index 338e5367a1d0df..56a59270b18af4 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_field/components/no_node_attributes_warning.tsx @@ -19,7 +19,7 @@ const i18nTexts = { 'xpack.indexLifecycleMgmt.editPolicy.warm.nodeAttributesMissingDescription', { defaultMessage: - 'Define custom node attributes in elasticsearch.yml to use attribute-based allocation. Warm nodes will be used instead.', + 'Define custom node attributes in elasticsearch.yml to use attribute-based allocation.', } ), }, @@ -28,7 +28,7 @@ const i18nTexts = { 'xpack.indexLifecycleMgmt.editPolicy.cold.nodeAttributesMissingDescription', { defaultMessage: - 'Define custom node attributes in elasticsearch.yml to use attribute-based allocation. Cold nodes will be used instead.', + 'Define custom node attributes in elasticsearch.yml to use attribute-based allocation.', } ), }, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_legacy_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_legacy_field.tsx deleted file mode 100644 index d64df468620e65..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/data_tier_allocation_legacy_field.tsx +++ /dev/null @@ -1,141 +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, { FunctionComponent } from 'react'; -import { i18n } from '@kbn/i18n'; -import { EuiDescribedFormGroup, EuiFormRow, EuiSpacer } from '@elastic/eui'; - -import { useKibana } from '../../../../../../shared_imports'; -import { PhaseWithAllocationAction, PhaseWithAllocation } from '../../../../../../../common/types'; -import { PhaseValidationErrors } from '../../../../../services/policies/policy_validation'; -import { getAvailableNodeRoleForPhase, isNodeRoleFirstPreference } from '../../../../../lib'; - -import { - DataTierAllocation, - DefaultAllocationNotice, - NoNodeAttributesWarning, - NodesDataProvider, - CloudDataTierCallout, -} from '../../data_tier_allocation'; - -const i18nTexts = { - title: i18n.translate('xpack.indexLifecycleMgmt.common.dataTier.title', { - defaultMessage: 'Data allocation', - }), -}; - -interface Props { - description: React.ReactNode; - phase: PhaseWithAllocation; - setPhaseData: (dataKey: keyof PhaseWithAllocationAction, value: string) => void; - isShowingErrors: boolean; - errors?: PhaseValidationErrors; - phaseData: PhaseWithAllocationAction; -} - -/** - * Top-level layout control for the data tier allocation field. - */ -export const DataTierAllocationFieldLegacy: FunctionComponent = ({ - description, - phase, - phaseData, - setPhaseData, - isShowingErrors, - errors, -}) => { - const { - services: { cloud }, - } = useKibana(); - - return ( - - {({ nodesByRoles, nodesByAttributes, isUsingDeprecatedDataRoleConfig }) => { - const hasDataNodeRoles = Object.keys(nodesByRoles).some((nodeRole) => - // match any of the "data_" roles, including data_content. - nodeRole.trim().startsWith('data_') - ); - const hasNodeAttrs = Boolean(Object.keys(nodesByAttributes ?? {}).length); - - const renderNotice = () => { - switch (phaseData.dataTierAllocationType) { - case 'default': - const isCloudEnabled = cloud?.isCloudEnabled ?? false; - if (isCloudEnabled && phase === 'cold') { - const isUsingNodeRolesAllocation = - !isUsingDeprecatedDataRoleConfig && hasDataNodeRoles; - const hasNoNodesWithNodeRole = !nodesByRoles.data_cold?.length; - - if (isUsingNodeRolesAllocation && hasNoNodesWithNodeRole) { - // Tell cloud users they can deploy nodes on cloud. - return ( - <> - - - - ); - } - } - - const allocationNodeRole = getAvailableNodeRoleForPhase(phase, nodesByRoles); - if ( - allocationNodeRole === 'none' || - !isNodeRoleFirstPreference(phase, allocationNodeRole) - ) { - return ( - <> - - - - ); - } - break; - case 'custom': - if (!hasNodeAttrs) { - return ( - <> - - - - ); - } - break; - default: - return null; - } - }; - - return ( - {i18nTexts.title}} - description={description} - fullWidth - > - - <> - - - {/* Data tier related warnings and call-to-action notices */} - {renderNotice()} - - - - ); - }} - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/index.ts index 0cae3eea6316b9..6355dab89771d7 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared/index.ts @@ -6,8 +6,6 @@ export { useRolloverPath } from '../../../constants'; -export { DataTierAllocationFieldLegacy } from './data_tier_allocation_legacy_field'; - export { DataTierAllocationField } from './data_tier_allocation_field'; export { Forcemerge } from './forcemerge_field'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx index 7b1a4f44b5de63..06c16e8bdd5ab4 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/warm_phase/warm_phase.tsx @@ -48,16 +48,21 @@ const i18nTexts = { const warmProperty: keyof Phases = 'warm'; +const formFieldPaths = { + enabled: '_meta.warm.enabled', + warmPhaseOnRollover: '_meta.warm.warmPhaseOnRollover', +}; + export const WarmPhase: FunctionComponent = () => { const { originalPolicy } = useEditPolicyContext(); const form = useFormContext(); const [formData] = useFormData({ - watch: [useRolloverPath, '_meta.warm.enabled', '_meta.warm.warmPhaseOnRollover'], + watch: [useRolloverPath, formFieldPaths.enabled, formFieldPaths.warmPhaseOnRollover], }); - const enabled = get(formData, '_meta.warm.enabled'); + const enabled = get(formData, formFieldPaths.enabled); const hotPhaseRolloverEnabled = get(formData, useRolloverPath); - const warmPhaseOnRollover = get(formData, '_meta.warm.warmPhaseOnRollover'); + const warmPhaseOnRollover = get(formData, formFieldPaths.warmPhaseOnRollover); const isShowingErrors = form.isValid === false; return ( @@ -88,7 +93,7 @@ export const WarmPhase: FunctionComponent = () => { />

{ {hotPhaseRolloverEnabled && ( = ({ ...legacyPolicy.phases, hot: p.phases.hot, warm: p.phases.warm, + cold: p.phases.cold, }, }); } else { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input_legacy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input_legacy.tsx deleted file mode 100644 index 5efbfabdf093d6..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/set_priority_input_legacy.tsx +++ /dev/null @@ -1,85 +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. - */ - -/** - * PLEASE NOTE: This component is currently duplicated. A version of this component wired up with - * the form lib lives in ./phases/shared - */ - -import React, { Fragment } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiFieldNumber, EuiTextColor, EuiDescribedFormGroup } from '@elastic/eui'; - -import { LearnMoreLink } from './'; -import { OptionalLabel } from './'; -import { ErrableFormRow } from './'; -import { PhaseWithIndexPriority, Phases } from '../../../../../common/types'; -import { PhaseValidationErrors, propertyof } from '../../../services/policies/policy_validation'; - -interface Props { - errors?: PhaseValidationErrors; - phase: keyof Phases & string; - phaseData: T; - setPhaseData: (dataKey: keyof T & string, value: any) => void; - isShowingErrors: boolean; -} -export const SetPriorityInput = ({ - errors, - phaseData, - phase, - setPhaseData, - isShowingErrors, -}: React.PropsWithChildren>) => { - const phaseIndexPriorityProperty = propertyof('phaseIndexPriority'); - return ( - - - - } - description={ - - {' '} - - - } - titleSize="xs" - fullWidth - > - - - - - } - isShowingErrors={isShowingErrors} - errors={errors?.phaseIndexPriority} - > - { - setPhaseData(phaseIndexPriorityProperty, e.target.value); - }} - min={0} - /> - - - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts index 760c6ad713ea04..f0294a5391d21d 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/deserializer.ts @@ -15,18 +15,27 @@ import { determineDataTierAllocationType } from '../../lib'; import { FormInternal } from './types'; export const deserializer = (policy: SerializedPolicy): FormInternal => { + const { + phases: { hot, warm, cold }, + } = policy; + const _meta: FormInternal['_meta'] = { hot: { - useRollover: Boolean(policy.phases.hot?.actions?.rollover), - forceMergeEnabled: Boolean(policy.phases.hot?.actions?.forcemerge), - bestCompression: policy.phases.hot?.actions?.forcemerge?.index_codec === 'best_compression', + useRollover: Boolean(hot?.actions?.rollover), + forceMergeEnabled: Boolean(hot?.actions?.forcemerge), + bestCompression: hot?.actions?.forcemerge?.index_codec === 'best_compression', }, warm: { - enabled: Boolean(policy.phases.warm), - warmPhaseOnRollover: Boolean(policy.phases.warm?.min_age === '0ms'), - forceMergeEnabled: Boolean(policy.phases.warm?.actions?.forcemerge), - bestCompression: policy.phases.warm?.actions?.forcemerge?.index_codec === 'best_compression', - dataTierAllocationType: determineDataTierAllocationType(policy.phases.warm?.actions), + enabled: Boolean(warm), + warmPhaseOnRollover: Boolean(warm?.min_age === '0ms'), + forceMergeEnabled: Boolean(warm?.actions?.forcemerge), + bestCompression: warm?.actions?.forcemerge?.index_codec === 'best_compression', + dataTierAllocationType: determineDataTierAllocationType(warm?.actions), + }, + cold: { + enabled: Boolean(cold), + dataTierAllocationType: determineDataTierAllocationType(cold?.actions), + freezeEnabled: Boolean(cold?.actions?.freeze), }, }; @@ -63,6 +72,20 @@ export const deserializer = (policy: SerializedPolicy): FormInternal => { draft._meta.warm.minAgeUnit = minAge.units; } } + + if (draft.phases.cold) { + if (draft.phases.cold.actions?.allocate?.require) { + Object.entries(draft.phases.cold.actions.allocate.require).forEach((entry) => { + draft._meta.cold.allocationNodeAttribute = entry.join(':'); + }); + } + + if (draft.phases.cold.min_age) { + const minAge = splitSizeAndUnits(draft.phases.cold.min_age); + draft.phases.cold.min_age = minAge.size; + draft._meta.cold.minAgeUnit = minAge.units; + } + } } ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx index eecdfb4871a676..5397f5da2d6bb2 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/edit_policy.tsx @@ -92,6 +92,7 @@ const mergeAllSerializedPolicies = ( ...legacySerializedPolicy.phases, hot: serializedPolicy.phases.hot, warm: serializedPolicy.phases.warm, + cold: serializedPolicy.phases.cold, }, }; }; @@ -195,10 +196,6 @@ export const EditPolicy: React.FunctionComponent = ({ [setPolicy] ); - const setColdPhaseData = useCallback( - (key: string, value: any) => setPhaseData('cold', key, value), - [setPhaseData] - ); const setDeletePhaseData = useCallback( (key: string, value: any) => setPhaseData('delete', key, value), [setPhaseData] @@ -342,14 +339,7 @@ export const EditPolicy: React.FunctionComponent = ({ - 0 - } - setPhaseData={setColdPhaseData} - phaseData={policy.phases.cold} - /> + diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts index a80382e87539c2..070f03f74b9549 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_schema.ts @@ -11,7 +11,11 @@ import { defaultSetPriority, defaultPhaseIndexPriority } from '../../constants'; import { FormInternal } from './types'; -import { ifExistsNumberGreaterThanZero, rolloverThresholdsValidator } from './form_validations'; +import { + ifExistsNumberGreaterThanZero, + ifExistsNumberNonNegative, + rolloverThresholdsValidator, +} from './form_validations'; import { i18nTexts } from './i18n_texts'; @@ -69,6 +73,30 @@ export const schema: FormSchema = { label: i18nTexts.editPolicy.allocationNodeAttributeFieldLabel, }, }, + cold: { + enabled: { + defaultValue: false, + label: i18n.translate( + 'xpack.indexLifecycleMgmt.editPolicy.coldPhase.activateColdPhaseSwitchLabel', + { defaultMessage: 'Activate cold phase' } + ), + }, + freezeEnabled: { + defaultValue: false, + label: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.freezeIndexLabel', { + defaultMessage: 'Freeze index', + }), + }, + minAgeUnit: { + defaultValue: 'd', + }, + dataTierAllocationType: { + label: i18nTexts.editPolicy.allocationTypeOptionsFieldLabel, + }, + allocationNodeAttribute: { + label: i18nTexts.editPolicy.allocationNodeAttributeFieldLabel, + }, + }, }, phases: { hot: { @@ -138,7 +166,7 @@ export const schema: FormSchema = { priority: { defaultValue: defaultSetPriority as any, label: i18nTexts.editPolicy.setPriorityFieldLabel, - validations: [{ validator: ifExistsNumberGreaterThanZero }], + validations: [{ validator: ifExistsNumberNonNegative }], serializer: serializers.stringToNumber, }, }, @@ -217,7 +245,48 @@ export const schema: FormSchema = { priority: { defaultValue: defaultPhaseIndexPriority as any, label: i18nTexts.editPolicy.setPriorityFieldLabel, - validations: [{ validator: ifExistsNumberGreaterThanZero }], + validations: [{ validator: ifExistsNumberNonNegative }], + serializer: serializers.stringToNumber, + }, + }, + }, + }, + cold: { + min_age: { + defaultValue: '0', + validations: [ + { + validator: (arg) => + numberGreaterThanField({ + than: 0, + allowEquality: true, + message: i18nTexts.editPolicy.errors.nonNegativeNumberRequired, + })({ + ...arg, + value: arg.value === '' ? -Infinity : parseInt(arg.value, 10), + }), + }, + ], + }, + actions: { + allocate: { + number_of_replicas: { + label: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasLabel', { + defaultMessage: 'Number of replicas (optional)', + }), + validations: [ + { + validator: ifExistsNumberGreaterThanZero, + }, + ], + serializer: serializers.stringToNumber, + }, + }, + set_priority: { + priority: { + defaultValue: '0' as any, + label: i18nTexts.editPolicy.setPriorityFieldLabel, + validations: [{ validator: ifExistsNumberNonNegative }], serializer: serializers.stringToNumber, }, }, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts index 37ca4e9def340f..9c855ccb41624f 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form_validations.ts @@ -12,18 +12,36 @@ import { i18nTexts } from './i18n_texts'; const { numberGreaterThanField } = fieldValidators; -export const ifExistsNumberGreaterThanZero: ValidationFunc = (arg) => { - if (arg.value) { - return numberGreaterThanField({ - than: 0, - message: i18nTexts.editPolicy.errors.numberGreatThan0Required, - })({ - ...arg, - value: parseInt(arg.value, 10), - }); - } +const createIfNumberExistsValidator = ({ + than, + message, +}: { + than: number; + message: string; +}): ValidationFunc => { + return (arg) => { + if (arg.value) { + return numberGreaterThanField({ + than, + message, + })({ + ...arg, + value: parseInt(arg.value, 10), + }); + } + }; }; +export const ifExistsNumberGreaterThanZero = createIfNumberExistsValidator({ + than: 0, + message: i18nTexts.editPolicy.errors.numberGreatThan0Required, +}); + +export const ifExistsNumberNonNegative = createIfNumberExistsValidator({ + than: -1, + message: i18nTexts.editPolicy.errors.nonNegativeNumberRequired, +}); + /** * A special validation type used to keep track of validation errors for * the rollover threshold values not being set (e.g., age and doc count) diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts index 90e81528f5afe6..564b5a2c4e3979 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/serializer.ts @@ -31,6 +31,11 @@ const serializeAllocateAction = ( [name]: value, }, }; + } else { + // The form has been configured to use node attribute based allocation but no node attribute + // was selected. We fall back to what was originally selected in this case. This might be + // migrate.enabled: "false" + actions.migrate = originalActions.migrate; } // copy over the original include and exclude values until we can set them in the form. @@ -129,5 +134,36 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => ( } } + /** + * COLD PHASE SERIALIZATION + */ + if (policy.phases.cold) { + if (policy.phases.cold.min_age) { + policy.phases.cold.min_age = `${policy.phases.cold.min_age}${_meta.cold.minAgeUnit}`; + } + + policy.phases.cold.actions = serializeAllocateAction( + _meta.cold, + policy.phases.cold.actions, + originalPolicy?.phases.cold?.actions + ); + + if ( + policy.phases.cold.actions.allocate && + !policy.phases.cold.actions.allocate.require && + !isNumber(policy.phases.cold.actions.allocate.number_of_replicas) && + isEmpty(policy.phases.cold.actions.allocate.include) && + isEmpty(policy.phases.cold.actions.allocate.exclude) + ) { + // remove allocate action if it does not define require or number of nodes + // and both include and exclude are empty objects (ES will fail to parse if we don't) + delete policy.phases.cold.actions.allocate; + } + + if (_meta.cold.freezeEnabled) { + policy.phases.cold.actions.freeze = {}; + } + } + return policy; }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts index 6fcfbd050c69d0..1884f8dbc06191 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts @@ -13,20 +13,29 @@ export interface DataAllocationMetaFields { allocationNodeAttribute?: string; } -interface HotPhaseMetaFields { - useRollover: boolean; +export interface MinAgeField { + minAgeUnit?: string; +} + +export interface ForcemergeFields { forceMergeEnabled: boolean; bestCompression: boolean; +} + +interface HotPhaseMetaFields extends ForcemergeFields { + useRollover: boolean; maxStorageSizeUnit?: string; maxAgeUnit?: string; } -interface WarmPhaseMetaFields extends DataAllocationMetaFields { +interface WarmPhaseMetaFields extends DataAllocationMetaFields, MinAgeField, ForcemergeFields { enabled: boolean; - forceMergeEnabled: boolean; - bestCompression: boolean; warmPhaseOnRollover: boolean; - minAgeUnit?: string; +} + +interface ColdPhaseMetaFields extends DataAllocationMetaFields, MinAgeField { + enabled: boolean; + freezeEnabled: boolean; } /** @@ -40,5 +49,6 @@ export interface FormInternal extends SerializedPolicy { _meta: { hot: HotPhaseMetaFields; warm: WarmPhaseMetaFields; + cold: ColdPhaseMetaFields; }; } diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/cold_phase.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/cold_phase.ts deleted file mode 100644 index faf3954f93fd8c..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/cold_phase.ts +++ /dev/null @@ -1,154 +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 { isEmpty } from 'lodash'; -import { AllocateAction, ColdPhase, SerializedColdPhase } from '../../../../common/types'; -import { serializedPhaseInitialization } from '../../constants'; -import { isNumber, splitSizeAndUnits } from './policy_serialization'; -import { - numberRequiredMessage, - PhaseValidationErrors, - positiveNumberRequiredMessage, -} from './policy_validation'; -import { determineDataTierAllocationTypeLegacy } from '../../lib'; -import { serializePhaseWithAllocation } from './shared'; - -export const coldPhaseInitialization: ColdPhase = { - phaseEnabled: false, - selectedMinimumAge: '0', - selectedMinimumAgeUnits: 'd', - selectedNodeAttrs: '', - selectedReplicaCount: '', - freezeEnabled: false, - phaseIndexPriority: '', - dataTierAllocationType: 'default', -}; - -export const coldPhaseFromES = (phaseSerialized?: SerializedColdPhase): ColdPhase => { - const phase = { ...coldPhaseInitialization }; - if (phaseSerialized === undefined || phaseSerialized === null) { - return phase; - } - - phase.phaseEnabled = true; - - if (phaseSerialized.actions) { - phase.dataTierAllocationType = determineDataTierAllocationTypeLegacy(phaseSerialized.actions); - } - - if (phaseSerialized.min_age) { - const { size: minAge, units: minAgeUnits } = splitSizeAndUnits(phaseSerialized.min_age); - phase.selectedMinimumAge = minAge; - phase.selectedMinimumAgeUnits = minAgeUnits; - } - - if (phaseSerialized.actions) { - const actions = phaseSerialized.actions; - if (actions.allocate) { - const allocate = actions.allocate; - if (allocate.require) { - Object.entries(allocate.require).forEach((entry) => { - phase.selectedNodeAttrs = entry.join(':'); - }); - if (allocate.number_of_replicas) { - phase.selectedReplicaCount = allocate.number_of_replicas.toString(); - } - } - } - - if (actions.freeze) { - phase.freezeEnabled = true; - } - - if (actions.set_priority) { - phase.phaseIndexPriority = actions.set_priority.priority - ? actions.set_priority.priority.toString() - : ''; - } - } - - return phase; -}; - -export const coldPhaseToES = ( - phase: ColdPhase, - originalPhase: SerializedColdPhase | undefined -): SerializedColdPhase => { - if (!originalPhase) { - originalPhase = { ...serializedPhaseInitialization }; - } - - const esPhase = { ...originalPhase }; - - if (isNumber(phase.selectedMinimumAge)) { - esPhase.min_age = `${phase.selectedMinimumAge}${phase.selectedMinimumAgeUnits}`; - } - - esPhase.actions = serializePhaseWithAllocation(phase, esPhase.actions); - - if (isNumber(phase.selectedReplicaCount)) { - esPhase.actions.allocate = esPhase.actions.allocate || ({} as AllocateAction); - esPhase.actions.allocate.number_of_replicas = parseInt(phase.selectedReplicaCount, 10); - } else { - if (esPhase.actions.allocate) { - delete esPhase.actions.allocate.number_of_replicas; - } - } - - if ( - esPhase.actions.allocate && - !esPhase.actions.allocate.require && - !isNumber(esPhase.actions.allocate.number_of_replicas) && - isEmpty(esPhase.actions.allocate.include) && - isEmpty(esPhase.actions.allocate.exclude) - ) { - // remove allocate action if it does not define require or number of nodes - // and both include and exclude are empty objects (ES will fail to parse if we don't) - delete esPhase.actions.allocate; - } - - if (phase.freezeEnabled) { - esPhase.actions.freeze = {}; - } else { - delete esPhase.actions.freeze; - } - - if (isNumber(phase.phaseIndexPriority)) { - esPhase.actions.set_priority = { - priority: parseInt(phase.phaseIndexPriority, 10), - }; - } else { - delete esPhase.actions.set_priority; - } - - return esPhase; -}; - -export const validateColdPhase = (phase: ColdPhase): PhaseValidationErrors => { - if (!phase.phaseEnabled) { - return {}; - } - - const phaseErrors = {} as PhaseValidationErrors; - - // index priority is optional, but if it's set, it needs to be a positive number - if (phase.phaseIndexPriority) { - if (!isNumber(phase.phaseIndexPriority)) { - phaseErrors.phaseIndexPriority = [numberRequiredMessage]; - } else if (parseInt(phase.phaseIndexPriority, 10) < 0) { - phaseErrors.phaseIndexPriority = [positiveNumberRequiredMessage]; - } - } - - // min age needs to be a positive number - if (!isNumber(phase.selectedMinimumAge)) { - phaseErrors.selectedMinimumAge = [numberRequiredMessage]; - } else if (parseInt(phase.selectedMinimumAge, 10) < 0) { - phaseErrors.selectedMinimumAge = [positiveNumberRequiredMessage]; - } - - return { ...phaseErrors }; -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts index 0be6ab35217360..19481b39a2c806 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.test.ts @@ -7,9 +7,7 @@ // eslint-disable-next-line no-restricted-imports import cloneDeep from 'lodash/cloneDeep'; import { deserializePolicy, legacySerializePolicy } from './policy_serialization'; -import { defaultNewColdPhase, defaultNewDeletePhase } from '../../constants'; -import { DataTierAllocationType } from '../../../../common/types'; -import { coldPhaseInitialization } from './cold_phase'; +import { defaultNewDeletePhase } from '../../constants'; describe('Policy serialization', () => { test('serialize a policy using "default" data allocation', () => { @@ -18,12 +16,6 @@ describe('Policy serialization', () => { { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - dataTierAllocationType: 'default', - selectedNodeAttrs: 'another:thing', - phaseEnabled: true, - }, delete: { ...defaultNewDeletePhase }, }, }, @@ -31,24 +23,12 @@ describe('Policy serialization', () => { name: 'test', phases: { hot: { actions: {} }, - cold: { - actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } }, - }, }, } ) ).toEqual({ name: 'test', - phases: { - cold: { - actions: { - set_priority: { - priority: 0, - }, - }, - min_age: '0d', - }, - }, + phases: {}, }); }); @@ -58,12 +38,6 @@ describe('Policy serialization', () => { { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - dataTierAllocationType: 'custom', - selectedNodeAttrs: 'another:thing', - phaseEnabled: true, - }, delete: { ...defaultNewDeletePhase }, }, }, @@ -71,37 +45,12 @@ describe('Policy serialization', () => { name: 'test', phases: { hot: { actions: {} }, - cold: { - actions: { - allocate: { - include: { keep: 'this' }, - exclude: { keep: 'this' }, - require: { something: 'here' }, - }, - }, - }, }, } ) ).toEqual({ name: 'test', - phases: { - cold: { - actions: { - allocate: { - include: { keep: 'this' }, - exclude: { keep: 'this' }, - require: { - another: 'thing', - }, - }, - set_priority: { - priority: 0, - }, - }, - min_age: '0d', - }, - }, + phases: {}, }); }); @@ -111,12 +60,6 @@ describe('Policy serialization', () => { { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - dataTierAllocationType: 'custom', - selectedNodeAttrs: '', - phaseEnabled: true, - }, delete: { ...defaultNewDeletePhase }, }, }, @@ -124,26 +67,13 @@ describe('Policy serialization', () => { name: 'test', phases: { hot: { actions: {} }, - cold: { - actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } }, - }, }, } ) ).toEqual({ // There should be no allocation action in any phases... name: 'test', - phases: { - cold: { - actions: { - allocate: { include: {}, exclude: {}, require: { something: 'here' } }, - set_priority: { - priority: 0, - }, - }, - min_age: '0d', - }, - }, + phases: {}, }); }); @@ -153,12 +83,6 @@ describe('Policy serialization', () => { { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - dataTierAllocationType: 'none', - selectedNodeAttrs: 'ignore:this', - phaseEnabled: true, - }, delete: { ...defaultNewDeletePhase }, }, }, @@ -166,39 +90,20 @@ describe('Policy serialization', () => { name: 'test', phases: { hot: { actions: {} }, - cold: { - actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } }, - }, }, } ) ).toEqual({ // There should be no allocation action in any phases... name: 'test', - phases: { - cold: { - actions: { - migrate: { - enabled: false, - }, - set_priority: { - priority: 0, - }, - }, - min_age: '0d', - }, - }, + phases: {}, }); }); test('serialization does not alter the original policy', () => { const originalPolicy = { name: 'test', - phases: { - cold: { - actions: { allocate: { include: {}, exclude: {}, require: { something: 'here' } } }, - }, - }, + phases: {}, }; const originalClone = cloneDeep(originalPolicy); @@ -206,13 +111,6 @@ describe('Policy serialization', () => { const deserializedPolicy = { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - dataTierAllocationType: 'none' as DataTierAllocationType, - selectedNodeAttrs: 'ignore:this', - phaseEnabled: true, - }, - delete: { ...defaultNewDeletePhase }, }, }; @@ -227,9 +125,6 @@ describe('Policy serialization', () => { { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - }, delete: { ...defaultNewDeletePhase }, }, }, @@ -276,9 +171,6 @@ describe('Policy serialization', () => { ).toEqual({ name: 'test', phases: { - cold: { - ...coldPhaseInitialization, - }, delete: { ...defaultNewDeletePhase }, }, }); @@ -290,9 +182,6 @@ describe('Policy serialization', () => { { name: 'test', phases: { - cold: { - ...defaultNewColdPhase, - }, delete: { ...defaultNewDeletePhase }, }, }, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts index 32c7e698b09203..55e9d88dcd383a 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_serialization.ts @@ -6,13 +6,8 @@ import { LegacyPolicy, PolicyFromES, SerializedPolicy } from '../../../../common/types'; -import { - defaultNewColdPhase, - defaultNewDeletePhase, - serializedPhaseInitialization, -} from '../../constants'; +import { defaultNewDeletePhase, serializedPhaseInitialization } from '../../constants'; -import { coldPhaseFromES, coldPhaseToES } from './cold_phase'; import { deletePhaseFromES, deletePhaseToES } from './delete_phase'; export const splitSizeAndUnits = (field: string): { size: string; units: string } => { @@ -46,7 +41,6 @@ export const initializeNewPolicy = (newPolicyName: string = ''): LegacyPolicy => return { name: newPolicyName, phases: { - cold: { ...defaultNewColdPhase }, delete: { ...defaultNewDeletePhase }, }, }; @@ -61,7 +55,6 @@ export const deserializePolicy = (policy: PolicyFromES): LegacyPolicy => { return { name, phases: { - cold: coldPhaseFromES(phases.cold), delete: deletePhaseFromES(phases.delete), }, }; @@ -79,10 +72,6 @@ export const legacySerializePolicy = ( phases: {}, } as SerializedPolicy; - if (policy.phases.cold.phaseEnabled) { - serializedPolicy.phases.cold = coldPhaseToES(policy.phases.cold, originalEsPolicy.phases.cold); - } - if (policy.phases.delete.phaseEnabled) { serializedPolicy.phases.delete = deletePhaseToES( policy.phases.delete, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts index a113cb68a23496..79c909c433f331 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/policy_validation.ts @@ -5,8 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import { ColdPhase, DeletePhase, LegacyPolicy, PolicyFromES } from '../../../../common/types'; -import { validateColdPhase } from './cold_phase'; +import { DeletePhase, LegacyPolicy, PolicyFromES } from '../../../../common/types'; import { validateDeletePhase } from './delete_phase'; export const propertyof = (propertyName: keyof T & string) => propertyName; @@ -82,7 +81,6 @@ export type PhaseValidationErrors = { }; export interface ValidationErrors { - cold: PhaseValidationErrors; delete: PhaseValidationErrors; policyName: string[]; } @@ -120,17 +118,12 @@ export const validatePolicy = ( } } - const coldPhaseErrors = validateColdPhase(policy.phases.cold); const deletePhaseErrors = validateDeletePhase(policy.phases.delete); - const isValid = - policyNameErrors.length === 0 && - Object.keys(coldPhaseErrors).length === 0 && - Object.keys(deletePhaseErrors).length === 0; + const isValid = policyNameErrors.length === 0 && Object.keys(deletePhaseErrors).length === 0; return [ isValid, { policyName: [...policyNameErrors], - cold: coldPhaseErrors, delete: deletePhaseErrors, }, ]; @@ -145,9 +138,6 @@ export const findFirstError = (errors?: ValidationErrors): string | undefined => return propertyof('policyName'); } - if (Object.keys(errors.cold).length > 0) { - return `${propertyof('cold')}.${Object.keys(errors.cold)[0]}`; - } if (Object.keys(errors.delete).length > 0) { return `${propertyof('delete')}.${Object.keys(errors.delete)[0]}`; } diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/serialize_phase_with_allocation.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/serialize_phase_with_allocation.ts deleted file mode 100644 index c29ae3ab228315..00000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/policies/shared/serialize_phase_with_allocation.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -// Prefer importing entire lodash library, e.g. import { get } from "lodash" -// eslint-disable-next-line no-restricted-imports -import cloneDeep from 'lodash/cloneDeep'; - -import { - AllocateAction, - PhaseWithAllocationAction, - SerializedPhase, -} from '../../../../../common/types'; - -export const serializePhaseWithAllocation = ( - phase: PhaseWithAllocationAction, - originalPhaseActions: SerializedPhase['actions'] = {} -): SerializedPhase['actions'] => { - const esPhaseActions: SerializedPhase['actions'] = cloneDeep(originalPhaseActions); - - if (phase.dataTierAllocationType === 'custom' && phase.selectedNodeAttrs) { - const [name, value] = phase.selectedNodeAttrs.split(':'); - esPhaseActions.allocate = esPhaseActions.allocate || ({} as AllocateAction); - esPhaseActions.allocate.require = { - [name]: value, - }; - } else if (phase.dataTierAllocationType === 'none') { - esPhaseActions.migrate = { enabled: false }; - if (esPhaseActions.allocate) { - delete esPhaseActions.allocate; - } - } else if (phase.dataTierAllocationType === 'default') { - if (esPhaseActions.allocate) { - delete esPhaseActions.allocate.require; - } - delete esPhaseActions.migrate; - } - - return esPhaseActions; -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts index c77e3d22f0e37c..2f1c7798e7a4d2 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts @@ -9,7 +9,6 @@ import { UIM_CONFIG_WARM_PHASE, UIM_CONFIG_SET_PRIORITY, UIM_CONFIG_FREEZE_INDEX, - defaultNewColdPhase, defaultPhaseIndexPriority, } from '../constants/'; @@ -23,7 +22,7 @@ describe('getUiMetricsForPhases', () => { min_age: '0ms', actions: { set_priority: { - priority: parseInt(defaultNewColdPhase.phaseIndexPriority, 10), + priority: parseInt(defaultPhaseIndexPriority, 10), }, }, }, @@ -69,7 +68,7 @@ describe('getUiMetricsForPhases', () => { actions: { freeze: {}, set_priority: { - priority: parseInt(defaultNewColdPhase.phaseIndexPriority, 10), + priority: parseInt(defaultPhaseIndexPriority, 10), }, }, }, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts index 305b35b23e4d8b..274d3d1ca97f3f 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts @@ -13,7 +13,6 @@ import { UIM_CONFIG_FREEZE_INDEX, UIM_CONFIG_SET_PRIORITY, UIM_CONFIG_WARM_PHASE, - defaultNewColdPhase, defaultSetPriority, defaultPhaseIndexPriority, } from '../constants'; @@ -55,8 +54,7 @@ export function getUiMetricsForPhases(phases: Phases): string[] { const isColdPhasePriorityChanged = phases.cold && phases.cold.actions.set_priority && - phases.cold.actions.set_priority.priority !== - parseInt(defaultNewColdPhase.phaseIndexPriority, 10); + phases.cold.actions.set_priority.priority !== parseInt(defaultPhaseIndexPriority, 10); // If the priority is different than the default, we'll consider it a user interaction, // even if the user has set it to undefined. return ( diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 043c1c3d7517e0..aec32563320250 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9086,7 +9086,6 @@ "xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeIndexExplanationText": "インデックスを読み取り専用にし、メモリー消費量を最小化します。", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeText": "凍結", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel": "レプリカを設定", - "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.allocationFieldLabel": "データティアオプション", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.helpText": "ノード属性に基づいてデータを移動します。", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.input": "カスタム", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.helpText": "コールドティアのノードにデータを移動します。", @@ -9150,7 +9149,6 @@ "xpack.indexLifecycleMgmt.editPolicy.nameLabel": "名前", "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.customOption.description": "ノード属性を使用して、シャード割り当てを制御します。{learnMoreLink}。", "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption": "割り当て構成を修正しない", - "xpack.indexLifecycleMgmt.editPolicy.nodeAllocationLabel": "ノード属性を選択", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesLoadingFailedTitle": "ノード属性を読み込めません", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingLabel": "カスタムノード属性が構成されていません", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesReloadButton": "再試行", @@ -9268,7 +9266,6 @@ "xpack.indexLifecycleMgmt.indexMgmtFilter.managedLabel": "管理中", "xpack.indexLifecycleMgmt.indexMgmtFilter.unmanagedLabel": "管理対象外", "xpack.indexLifecycleMgmt.indexMgmtFilter.warmLabel": "ウォーム", - "xpack.indexLifecycleMgmt.indexPriorityLabel": "インデックスの優先順位", "xpack.indexLifecycleMgmt.learnMore": "その他のリソース", "xpack.indexLifecycleMgmt.licenseCheckErrorMessage": "ライセンス確認失敗", "xpack.indexLifecycleMgmt.nodeAttrDetails.hostField": "ホスト", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 886f58a9c50d68..cd56a96ac07096 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9095,7 +9095,6 @@ "xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeIndexExplanationText": "使索引只读,并最大限度减小其内存占用。", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeText": "冻结", "xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel": "设置副本", - "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.allocationFieldLabel": "数据层选项", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.helpText": "根据节点属性移动数据。", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.input": "定制", "xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.helpText": "将数据移到冷层中的节点。", @@ -9159,7 +9158,6 @@ "xpack.indexLifecycleMgmt.editPolicy.nameLabel": "名称", "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.customOption.description": "使用节点属性控制分片分配。{learnMoreLink}。", "xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption": "不要修改分配配置", - "xpack.indexLifecycleMgmt.editPolicy.nodeAllocationLabel": "选择节点属性", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesLoadingFailedTitle": "无法加载节点属性", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesMissingLabel": "未配置定制节点属性", "xpack.indexLifecycleMgmt.editPolicy.nodeAttributesReloadButton": "重试", @@ -9277,7 +9275,6 @@ "xpack.indexLifecycleMgmt.indexMgmtFilter.managedLabel": "受管", "xpack.indexLifecycleMgmt.indexMgmtFilter.unmanagedLabel": "未受管", "xpack.indexLifecycleMgmt.indexMgmtFilter.warmLabel": "温", - "xpack.indexLifecycleMgmt.indexPriorityLabel": "索引优先级", "xpack.indexLifecycleMgmt.learnMore": "了解详情", "xpack.indexLifecycleMgmt.licenseCheckErrorMessage": "许可证检查失败", "xpack.indexLifecycleMgmt.nodeAttrDetails.hostField": "主机",