[ILM] Policy phases redesign (#88671)
* Phases redesign * Title and name field layout * Active highlight wip * Copy comments * Updated data allocation dropdown * Min age error message * Fixed tests * Fixed edit policy integration tests * Fixed more tests * Cleaned up test files * Use hotProperty instead of a string * Clean up in phase component * Fixed i18n files * Updated optional fields * Updated aria attributes after running axe tests * Added review suggestions * Reversed data allocation field changes * Fixed type error * Reversed on/off label and prepend input label * Deleted property consts from phases components * Removed not needed i18n consts and added i18n where missing * Fixed merge conflicts with master Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
0a7a9e4933
commit
d931ed61e4
|
@ -21,6 +21,9 @@ const PERCENT_SIGN_NAME = 'test%';
|
|||
const PERCENT_SIGN_WITH_OTHER_CHARS_NAME = 'test%#';
|
||||
const PERCENT_SIGN_25_SEQUENCE = 'test%25';
|
||||
|
||||
const createPolicyTitle = 'Create Policy';
|
||||
const editPolicyTitle = 'Edit Policy';
|
||||
|
||||
window.scrollTo = jest.fn();
|
||||
|
||||
jest.mock('@elastic/eui', () => {
|
||||
|
@ -52,7 +55,7 @@ describe('<App />', () => {
|
|||
await actions.clickCreatePolicyButton();
|
||||
component.update();
|
||||
|
||||
expect(testBed.find('policyTitle').text()).toBe(`Create an index lifecycle policy`);
|
||||
expect(testBed.find('policyTitle').text()).toBe(createPolicyTitle);
|
||||
expect(testBed.find('policyNameField').props().value).toBe('');
|
||||
});
|
||||
|
||||
|
@ -68,7 +71,7 @@ describe('<App />', () => {
|
|||
await actions.clickCreatePolicyButton();
|
||||
component.update();
|
||||
|
||||
expect(testBed.find('policyTitle').text()).toBe(`Create an index lifecycle policy`);
|
||||
expect(testBed.find('policyTitle').text()).toBe(createPolicyTitle);
|
||||
expect(testBed.find('policyNameField').props().value).toBe('');
|
||||
});
|
||||
});
|
||||
|
@ -89,9 +92,7 @@ describe('<App />', () => {
|
|||
await actions.clickPolicyNameLink();
|
||||
component.update();
|
||||
|
||||
expect(testBed.find('policyTitle').text()).toBe(
|
||||
`Edit index lifecycle policy ${SPECIAL_CHARS_NAME}`
|
||||
);
|
||||
expect(testBed.find('policyTitle').text()).toBe(`${editPolicyTitle} ${SPECIAL_CHARS_NAME}`);
|
||||
});
|
||||
|
||||
test('loading edit policy page url works', async () => {
|
||||
|
@ -102,9 +103,7 @@ describe('<App />', () => {
|
|||
const { component } = testBed;
|
||||
component.update();
|
||||
|
||||
expect(testBed.find('policyTitle').text()).toBe(
|
||||
`Edit index lifecycle policy ${SPECIAL_CHARS_NAME}`
|
||||
);
|
||||
expect(testBed.find('policyTitle').text()).toBe(`${editPolicyTitle} ${SPECIAL_CHARS_NAME}`);
|
||||
});
|
||||
|
||||
// using double encoding to counteract react-router's v5 internal decodeURI call
|
||||
|
@ -117,9 +116,7 @@ describe('<App />', () => {
|
|||
const { component } = testBed;
|
||||
component.update();
|
||||
|
||||
expect(testBed.find('policyTitle').text()).toBe(
|
||||
`Edit index lifecycle policy ${SPECIAL_CHARS_NAME}`
|
||||
);
|
||||
expect(testBed.find('policyTitle').text()).toBe(`${editPolicyTitle} ${SPECIAL_CHARS_NAME}`);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -136,9 +133,7 @@ describe('<App />', () => {
|
|||
const { component } = testBed;
|
||||
component.update();
|
||||
|
||||
expect(testBed.find('policyTitle').text()).toBe(
|
||||
`Edit index lifecycle policy ${PERCENT_SIGN_NAME}`
|
||||
);
|
||||
expect(testBed.find('policyTitle').text()).toBe(`${editPolicyTitle} ${PERCENT_SIGN_NAME}`);
|
||||
});
|
||||
|
||||
test('loading edit policy page url with double encoding works', async () => {
|
||||
|
@ -149,9 +144,7 @@ describe('<App />', () => {
|
|||
const { component } = testBed;
|
||||
component.update();
|
||||
|
||||
expect(testBed.find('policyTitle').text()).toBe(
|
||||
`Edit index lifecycle policy ${PERCENT_SIGN_NAME}`
|
||||
);
|
||||
expect(testBed.find('policyTitle').text()).toBe(`${editPolicyTitle} ${PERCENT_SIGN_NAME}`);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -174,7 +167,7 @@ describe('<App />', () => {
|
|||
component.update();
|
||||
|
||||
expect(testBed.find('policyTitle').text()).toBe(
|
||||
`Edit index lifecycle policy ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}`
|
||||
`${editPolicyTitle} ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -188,7 +181,7 @@ describe('<App />', () => {
|
|||
|
||||
// known issue https://github.com/elastic/kibana/issues/82440
|
||||
expect(testBed.find('policyTitle').text()).not.toBe(
|
||||
`Edit index lifecycle policy ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}`
|
||||
`${editPolicyTitle} ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -203,7 +196,7 @@ describe('<App />', () => {
|
|||
component.update();
|
||||
|
||||
expect(testBed.find('policyTitle').text()).toBe(
|
||||
`Edit index lifecycle policy ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}`
|
||||
`${editPolicyTitle} ${PERCENT_SIGN_WITH_OTHER_CHARS_NAME}`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -225,7 +218,7 @@ describe('<App />', () => {
|
|||
component.update();
|
||||
|
||||
expect(testBed.find('policyTitle').text()).toBe(
|
||||
`Edit index lifecycle policy ${PERCENT_SIGN_25_SEQUENCE}`
|
||||
`${editPolicyTitle} ${PERCENT_SIGN_25_SEQUENCE}`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -239,7 +232,7 @@ describe('<App />', () => {
|
|||
|
||||
// known issue https://github.com/elastic/kibana/issues/82440
|
||||
expect(testBed.find('policyTitle').text()).not.toBe(
|
||||
`Edit index lifecycle policy ${PERCENT_SIGN_25_SEQUENCE}`
|
||||
`${editPolicyTitle} ${PERCENT_SIGN_25_SEQUENCE}`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -254,7 +247,7 @@ describe('<App />', () => {
|
|||
component.update();
|
||||
|
||||
expect(testBed.find('policyTitle').text()).toBe(
|
||||
`Edit index lifecycle policy ${PERCENT_SIGN_25_SEQUENCE}`
|
||||
`${editPolicyTitle} ${PERCENT_SIGN_25_SEQUENCE}`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -89,6 +89,13 @@ export const setup = async (arg?: { appServicesContext: Partial<AppServicesConte
|
|||
component.update();
|
||||
};
|
||||
|
||||
const createFormCheckboxAction = (dataTestSubject: string) => async (checked: boolean) => {
|
||||
await act(async () => {
|
||||
form.selectCheckBox(dataTestSubject, checked);
|
||||
});
|
||||
component.update();
|
||||
};
|
||||
|
||||
function createFormSetValueAction<V extends string = string>(dataTestSubject: string) {
|
||||
return async (value: V) => {
|
||||
await act(async () => {
|
||||
|
@ -146,17 +153,21 @@ export const setup = async (arg?: { appServicesContext: Partial<AppServicesConte
|
|||
forceMergeFieldExists: () => exists(toggleSelector),
|
||||
toggleForceMerge: createFormToggleAction(toggleSelector),
|
||||
setForcemergeSegmentsCount: createFormSetValueAction(`${phase}-selectedForceMergeSegments`),
|
||||
setBestCompression: createFormToggleAction(`${phase}-bestCompression`),
|
||||
setBestCompression: createFormCheckboxAction(`${phase}-bestCompression`),
|
||||
};
|
||||
};
|
||||
|
||||
const setIndexPriority = (phase: Phases) =>
|
||||
createFormSetValueAction(`${phase}-phaseIndexPriority`);
|
||||
const createIndexPriorityActions = (phase: Phases) => {
|
||||
const toggleSelector = `${phase}-indexPrioritySwitch`;
|
||||
return {
|
||||
indexPriorityExists: () => exists(toggleSelector),
|
||||
toggleIndexPriority: createFormToggleAction(toggleSelector),
|
||||
setIndexPriority: createFormSetValueAction(`${phase}-indexPriority`),
|
||||
};
|
||||
};
|
||||
|
||||
const enable = (phase: Phases) => createFormToggleAction(`enablePhaseSwitch-${phase}`);
|
||||
|
||||
const warmPhaseOnRollover = createFormToggleAction(`warm-warmPhaseOnRollover`);
|
||||
|
||||
const setMinAgeValue = (phase: Phases) => createFormSetValueAction(`${phase}-selectedMinimumAge`);
|
||||
|
||||
const setMinAgeUnits = (phase: Phases) =>
|
||||
|
@ -190,13 +201,15 @@ export const setup = async (arg?: { appServicesContext: Partial<AppServicesConte
|
|||
await createFormSetValueAction(`${phase}-selectedReplicaCount`)(value);
|
||||
};
|
||||
|
||||
const setShrink = (phase: Phases) => async (value: string) => {
|
||||
await createFormToggleAction(`${phase}-shrinkSwitch`)(true);
|
||||
await createFormSetValueAction(`${phase}-selectedPrimaryShardCount`)(value);
|
||||
const createShrinkActions = (phase: Phases) => {
|
||||
const toggleSelector = `${phase}-shrinkSwitch`;
|
||||
return {
|
||||
shrinkExists: () => exists(toggleSelector),
|
||||
toggleShrink: createFormToggleAction(toggleSelector),
|
||||
setShrink: createFormSetValueAction(`${phase}-primaryShardCount`),
|
||||
};
|
||||
};
|
||||
|
||||
const shrinkExists = (phase: Phases) => () => exists(`${phase}-shrinkSwitch`);
|
||||
|
||||
const setFreeze = createFormToggleAction('freezeSwitch');
|
||||
const freezeExists = () => exists('freezeSwitch');
|
||||
|
||||
|
@ -250,25 +263,22 @@ export const setup = async (arg?: { appServicesContext: Partial<AppServicesConte
|
|||
toggleRollover,
|
||||
toggleDefaultRollover,
|
||||
...createForceMergeActions('hot'),
|
||||
setIndexPriority: setIndexPriority('hot'),
|
||||
setShrink: setShrink('hot'),
|
||||
shrinkExists: shrinkExists('hot'),
|
||||
...createIndexPriorityActions('hot'),
|
||||
...createShrinkActions('hot'),
|
||||
setReadonly: setReadonly('hot'),
|
||||
...createSearchableSnapshotActions('hot'),
|
||||
},
|
||||
warm: {
|
||||
enable: enable('warm'),
|
||||
warmPhaseOnRollover,
|
||||
setMinAgeValue: setMinAgeValue('warm'),
|
||||
setMinAgeUnits: setMinAgeUnits('warm'),
|
||||
setDataAllocation: setDataAllocation('warm'),
|
||||
setSelectedNodeAttribute: setSelectedNodeAttribute('warm'),
|
||||
setReplicas: setReplicas('warm'),
|
||||
setShrink: setShrink('warm'),
|
||||
shrinkExists: shrinkExists('warm'),
|
||||
...createShrinkActions('warm'),
|
||||
...createForceMergeActions('warm'),
|
||||
setReadonly: setReadonly('warm'),
|
||||
setIndexPriority: setIndexPriority('warm'),
|
||||
...createIndexPriorityActions('warm'),
|
||||
},
|
||||
cold: {
|
||||
enable: enable('cold'),
|
||||
|
@ -279,7 +289,7 @@ export const setup = async (arg?: { appServicesContext: Partial<AppServicesConte
|
|||
setReplicas: setReplicas('cold'),
|
||||
setFreeze,
|
||||
freezeExists,
|
||||
setIndexPriority: setIndexPriority('cold'),
|
||||
...createIndexPriorityActions('cold'),
|
||||
...createSearchableSnapshotActions('cold'),
|
||||
},
|
||||
delete: {
|
||||
|
|
|
@ -76,9 +76,6 @@ describe('<EditPolicy />', () => {
|
|||
max_size: '50gb',
|
||||
unknown_setting: 123, // Made up setting that should stay preserved
|
||||
},
|
||||
set_priority: {
|
||||
priority: 100,
|
||||
},
|
||||
},
|
||||
min_age: '0ms',
|
||||
},
|
||||
|
@ -126,8 +123,10 @@ describe('<EditPolicy />', () => {
|
|||
await actions.hot.toggleForceMerge(true);
|
||||
await actions.hot.setForcemergeSegmentsCount('123');
|
||||
await actions.hot.setBestCompression(true);
|
||||
await actions.hot.toggleShrink(true);
|
||||
await actions.hot.setShrink('2');
|
||||
await actions.hot.setReadonly(true);
|
||||
await actions.hot.toggleIndexPriority(true);
|
||||
await actions.hot.setIndexPriority('123');
|
||||
|
||||
await actions.savePolicy();
|
||||
|
@ -186,13 +185,7 @@ describe('<EditPolicy />', () => {
|
|||
const hotActions = policy.phases.hot.actions;
|
||||
const rolloverAction = hotActions.rollover;
|
||||
expect(rolloverAction).toBe(undefined);
|
||||
expect(hotActions).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"set_priority": Object {
|
||||
"priority": 100,
|
||||
},
|
||||
}
|
||||
`);
|
||||
expect(hotActions).toMatchInlineSnapshot(`Object {}`);
|
||||
});
|
||||
|
||||
test('enabling searchable snapshot should hide force merge, freeze and shrink in subsequent phases', async () => {
|
||||
|
@ -260,6 +253,7 @@ describe('<EditPolicy />', () => {
|
|||
"priority": 50,
|
||||
},
|
||||
},
|
||||
"min_age": "0ms",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -270,6 +264,7 @@ describe('<EditPolicy />', () => {
|
|||
await actions.warm.setDataAllocation('node_attrs');
|
||||
await actions.warm.setSelectedNodeAttribute('test:123');
|
||||
await actions.warm.setReplicas('123');
|
||||
await actions.warm.toggleShrink(true);
|
||||
await actions.warm.setShrink('123');
|
||||
await actions.warm.toggleForceMerge(true);
|
||||
await actions.warm.setForcemergeSegmentsCount('123');
|
||||
|
@ -290,9 +285,6 @@ describe('<EditPolicy />', () => {
|
|||
"max_age": "30d",
|
||||
"max_size": "50gb",
|
||||
},
|
||||
"set_priority": Object {
|
||||
"priority": 100,
|
||||
},
|
||||
},
|
||||
"min_age": "0ms",
|
||||
},
|
||||
|
@ -316,24 +308,12 @@ describe('<EditPolicy />', () => {
|
|||
"number_of_shards": 123,
|
||||
},
|
||||
},
|
||||
"min_age": "0ms",
|
||||
},
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
test('setting warm phase on rollover to "false"', async () => {
|
||||
const { actions } = testBed;
|
||||
await actions.warm.enable(true);
|
||||
await actions.warm.warmPhaseOnRollover(false);
|
||||
await actions.warm.setMinAgeValue('123');
|
||||
await actions.warm.setMinAgeUnits('d');
|
||||
await actions.savePolicy();
|
||||
const latestRequest = server.requests[server.requests.length - 1];
|
||||
const warmPhaseMinAge = JSON.parse(JSON.parse(latestRequest.requestBody).body).phases.warm
|
||||
.min_age;
|
||||
expect(warmPhaseMinAge).toBe('123d');
|
||||
});
|
||||
});
|
||||
|
||||
describe('policy with include and exclude', () => {
|
||||
|
@ -458,9 +438,6 @@ describe('<EditPolicy />', () => {
|
|||
"max_age": "30d",
|
||||
"max_size": "50gb",
|
||||
},
|
||||
"set_priority": Object {
|
||||
"priority": 100,
|
||||
},
|
||||
},
|
||||
"min_age": "0ms",
|
||||
},
|
||||
|
@ -662,9 +639,6 @@ describe('<EditPolicy />', () => {
|
|||
"allocate": Object {
|
||||
"number_of_replicas": 123,
|
||||
},
|
||||
"set_priority": Object {
|
||||
"priority": 50,
|
||||
},
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
|
|
@ -157,7 +157,7 @@ const setPhaseIndexPriority = async (
|
|||
phase: string,
|
||||
priority: string | number
|
||||
) => {
|
||||
const priorityInput = findTestSubject(rendered, `${phase}-phaseIndexPriority`);
|
||||
const priorityInput = findTestSubject(rendered, `${phase}-indexPriority`);
|
||||
await act(async () => {
|
||||
priorityInput.simulate('change', { target: { value: priority } });
|
||||
});
|
||||
|
@ -324,9 +324,6 @@ describe('edit policy', () => {
|
|||
max_age: '30d',
|
||||
max_size: '50gb',
|
||||
},
|
||||
set_priority: {
|
||||
priority: 100,
|
||||
},
|
||||
},
|
||||
min_age: '0ms',
|
||||
},
|
||||
|
@ -451,6 +448,7 @@ describe('edit policy', () => {
|
|||
const rendered = mountWithIntl(component);
|
||||
await noRollover(rendered);
|
||||
await setPolicyName(rendered, 'mypolicy');
|
||||
|
||||
await setPhaseIndexPriority(rendered, 'hot', '-1');
|
||||
waitForFormLibValidation(rendered);
|
||||
expectedErrorMessages(rendered, [i18nTexts.editPolicy.errors.nonNegativeNumberRequired]);
|
||||
|
@ -512,7 +510,7 @@ describe('edit policy', () => {
|
|||
});
|
||||
rendered.update();
|
||||
await setPhaseAfter(rendered, 'warm', '1');
|
||||
const shrinkInput = findTestSubject(rendered, 'warm-selectedPrimaryShardCount');
|
||||
const shrinkInput = findTestSubject(rendered, 'warm-primaryShardCount');
|
||||
await act(async () => {
|
||||
shrinkInput.simulate('change', { target: { value: '0' } });
|
||||
});
|
||||
|
@ -529,7 +527,7 @@ describe('edit policy', () => {
|
|||
findTestSubject(rendered, 'warm-shrinkSwitch').simulate('click');
|
||||
});
|
||||
rendered.update();
|
||||
const shrinkInput = findTestSubject(rendered, 'warm-selectedPrimaryShardCount');
|
||||
const shrinkInput = findTestSubject(rendered, 'warm-primaryShardCount');
|
||||
await act(async () => {
|
||||
shrinkInput.simulate('change', { target: { value: '-1' } });
|
||||
});
|
||||
|
@ -845,7 +843,7 @@ describe('edit policy', () => {
|
|||
await activatePhase(rendered, 'warm');
|
||||
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
|
||||
|
||||
// Assert that only the custom and off options exist
|
||||
// Assert that default, custom and 'none' options exist
|
||||
findTestSubject(rendered, 'dataTierSelect').simulate('click');
|
||||
expect(findTestSubject(rendered, 'defaultDataAllocationOption').exists()).toBeTruthy();
|
||||
expect(findTestSubject(rendered, 'customDataAllocationOption').exists()).toBeTruthy();
|
||||
|
@ -885,7 +883,7 @@ describe('edit policy', () => {
|
|||
await activatePhase(rendered, 'warm');
|
||||
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
|
||||
|
||||
// Assert that only the custom and off options exist
|
||||
// Assert that default, custom and 'none' options exist
|
||||
findTestSubject(rendered, 'dataTierSelect').simulate('click');
|
||||
expect(findTestSubject(rendered, 'defaultDataAllocationOption').exists()).toBeFalsy();
|
||||
expect(findTestSubject(rendered, 'customDataAllocationOption').exists()).toBeTruthy();
|
||||
|
|
|
@ -4,16 +4,13 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import {
|
||||
SerializedPhase,
|
||||
DeletePhase,
|
||||
SerializedPolicy,
|
||||
RolloverAction,
|
||||
} from '../../../common/types';
|
||||
import { SerializedPolicy, RolloverAction } from '../../../common/types';
|
||||
|
||||
export const defaultSetPriority: string = '100';
|
||||
|
||||
export const defaultPhaseIndexPriority: string = '50';
|
||||
export const defaultIndexPriority = {
|
||||
hot: '100',
|
||||
warm: '50',
|
||||
cold: '0',
|
||||
};
|
||||
|
||||
export const defaultRolloverAction: RolloverAction = {
|
||||
max_age: '30d',
|
||||
|
@ -30,15 +27,3 @@ export const defaultPolicy: SerializedPolicy = {
|
|||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const defaultNewDeletePhase: DeletePhase = {
|
||||
phaseEnabled: false,
|
||||
selectedMinimumAge: '0',
|
||||
selectedMinimumAgeUnits: 'd',
|
||||
waitForSnapshotPolicy: '',
|
||||
};
|
||||
|
||||
export const serializedPhaseInitialization: SerializedPhase = {
|
||||
min_age: '0ms',
|
||||
actions: {},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
.ilmActivePhaseHighlight {
|
||||
border-left: $euiBorderWidthThin solid $euiColorLightShade;
|
||||
height: 100%;
|
||||
|
||||
&.hotPhase.active {
|
||||
border-left-color: $euiColorVis9_behindText;
|
||||
}
|
||||
|
||||
&.warmPhase.active {
|
||||
border-left-color: $euiColorVis5_behindText;
|
||||
}
|
||||
|
||||
&.coldPhase.active {
|
||||
border-left-color: $euiColorVis1_behindText;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FunctionComponent } from 'react';
|
||||
|
||||
import './active_highlight.scss';
|
||||
|
||||
interface Props {
|
||||
phase: 'hot' | 'warm' | 'cold';
|
||||
enabled: boolean;
|
||||
}
|
||||
export const ActiveHighlight: FunctionComponent<Props> = ({ phase, enabled }) => {
|
||||
return <div className={`ilmActivePhaseHighlight ${phase}Phase ${enabled ? 'active' : ''} `} />;
|
||||
};
|
|
@ -4,4 +4,4 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { MinAgeInputField } from './min_age_input_field';
|
||||
export { ActiveHighlight } from './active_highlight';
|
|
@ -11,6 +11,7 @@ export { OptionalLabel } from './optional_label';
|
|||
export { PolicyJsonFlyout } from './policy_json_flyout';
|
||||
export { DescribedFormRow, ToggleFieldWithDescribedFormRow } from './described_form_row';
|
||||
export { FieldLoadingError } from './field_loading_error';
|
||||
export { ActiveHighlight } from './active_highlight';
|
||||
export { Timeline } from './timeline';
|
||||
|
||||
export * from './phases';
|
||||
|
|
|
@ -9,28 +9,21 @@ import { FormattedMessage } from '@kbn/i18n/react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { get } from 'lodash';
|
||||
|
||||
import { EuiDescribedFormGroup, EuiTextColor, EuiAccordion } from '@elastic/eui';
|
||||
import { EuiTextColor } from '@elastic/eui';
|
||||
|
||||
import { Phases } from '../../../../../../../common/types';
|
||||
import { useFormData } from '../../../../../../shared_imports';
|
||||
|
||||
import { useFormData, UseField, ToggleField, NumericField } from '../../../../../../shared_imports';
|
||||
|
||||
import { useEditPolicyContext } from '../../../edit_policy_context';
|
||||
import { useConfigurationIssues } from '../../../form';
|
||||
|
||||
import {
|
||||
LearnMoreLink,
|
||||
ActiveBadge,
|
||||
DescribedFormRow,
|
||||
ToggleFieldWithDescribedFormRow,
|
||||
} from '../../';
|
||||
import { LearnMoreLink, ToggleFieldWithDescribedFormRow } from '../../';
|
||||
|
||||
import {
|
||||
MinAgeInputField,
|
||||
DataTierAllocationField,
|
||||
SetPriorityInputField,
|
||||
SearchableSnapshotField,
|
||||
IndexPriorityField,
|
||||
ReplicasField,
|
||||
} from '../shared_fields';
|
||||
import { Phase } from '../phase';
|
||||
|
||||
const i18nTexts = {
|
||||
dataTierAllocation: {
|
||||
|
@ -41,166 +34,64 @@ const i18nTexts = {
|
|||
},
|
||||
};
|
||||
|
||||
const coldProperty: keyof Phases = 'cold';
|
||||
|
||||
const formFieldPaths = {
|
||||
enabled: '_meta.cold.enabled',
|
||||
searchableSnapshot: 'phases.cold.actions.searchable_snapshot.snapshot_repository',
|
||||
};
|
||||
|
||||
export const ColdPhase: FunctionComponent = () => {
|
||||
const { policy } = useEditPolicyContext();
|
||||
const { isUsingSearchableSnapshotInHotPhase } = useConfigurationIssues();
|
||||
|
||||
const [formData] = useFormData({
|
||||
watch: [formFieldPaths.enabled, formFieldPaths.searchableSnapshot],
|
||||
watch: [formFieldPaths.searchableSnapshot],
|
||||
});
|
||||
|
||||
const enabled = get(formData, formFieldPaths.enabled);
|
||||
const showReplicasField = get(formData, formFieldPaths.searchableSnapshot) == null;
|
||||
|
||||
return (
|
||||
<div id="coldPhaseContent" aria-live="polite" role="region">
|
||||
<>
|
||||
{/* Section title group; containing min age */}
|
||||
<EuiDescribedFormGroup
|
||||
<Phase phase={'cold'}>
|
||||
<SearchableSnapshotField phase={'cold'} />
|
||||
|
||||
{showReplicasField && <ReplicasField phase={'cold'} />}
|
||||
|
||||
{/* Freeze section */}
|
||||
{!isUsingSearchableSnapshotInHotPhase && (
|
||||
<ToggleFieldWithDescribedFormRow
|
||||
title={
|
||||
<div>
|
||||
<h2 className="eui-displayInlineBlock eui-alignMiddle">
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseLabel"
|
||||
defaultMessage="Cold phase"
|
||||
/>
|
||||
</h2>{' '}
|
||||
{enabled && <ActiveBadge />}
|
||||
</div>
|
||||
}
|
||||
titleSize="s"
|
||||
description={
|
||||
<>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseDescriptionText"
|
||||
defaultMessage="You are querying your index less frequently, so you can allocate shards
|
||||
on significantly less performant hardware.
|
||||
Because your queries are slower, you can reduce the number of replicas."
|
||||
/>
|
||||
</p>
|
||||
<UseField
|
||||
path={formFieldPaths.enabled}
|
||||
component={ToggleField}
|
||||
componentProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': 'enablePhaseSwitch-cold',
|
||||
'aria-controls': 'coldPhaseContent',
|
||||
},
|
||||
}}
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeText"
|
||||
defaultMessage="Freeze"
|
||||
/>
|
||||
</>
|
||||
</h3>
|
||||
}
|
||||
description={
|
||||
<EuiTextColor color="subdued">
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeIndexExplanationText"
|
||||
defaultMessage="Make the index read-only and minimize its memory footprint."
|
||||
/>{' '}
|
||||
<LearnMoreLink docPath="ilm-freeze.html" />
|
||||
</EuiTextColor>
|
||||
}
|
||||
fullWidth
|
||||
titleSize="xs"
|
||||
switchProps={{
|
||||
'data-test-subj': 'freezeSwitch',
|
||||
path: '_meta.cold.freezeEnabled',
|
||||
}}
|
||||
>
|
||||
{enabled && <MinAgeInputField phase="cold" />}
|
||||
</EuiDescribedFormGroup>
|
||||
{enabled && (
|
||||
<>
|
||||
<SearchableSnapshotField phase="cold" />
|
||||
<div />
|
||||
</ToggleFieldWithDescribedFormRow>
|
||||
)}
|
||||
|
||||
<EuiAccordion
|
||||
id="ilmWarmPhaseAdvancedSettings"
|
||||
buttonContent={i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.warmPhase.advancedSettingsButton',
|
||||
{
|
||||
defaultMessage: 'Advanced settings',
|
||||
}
|
||||
)}
|
||||
paddingSize="m"
|
||||
>
|
||||
{
|
||||
/* Replicas section */
|
||||
showReplicasField && (
|
||||
<DescribedFormRow
|
||||
title={
|
||||
<h3>
|
||||
{i18n.translate('xpack.indexLifecycleMgmt.coldPhase.replicasTitle', {
|
||||
defaultMessage: 'Replicas',
|
||||
})}
|
||||
</h3>
|
||||
}
|
||||
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:
|
||||
policy.phases.cold?.actions?.allocate?.number_of_replicas != null,
|
||||
}}
|
||||
fullWidth
|
||||
>
|
||||
<UseField
|
||||
path="phases.cold.actions.allocate.number_of_replicas"
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${coldProperty}-selectedReplicaCount`,
|
||||
min: 0,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</DescribedFormRow>
|
||||
)
|
||||
}
|
||||
{/* Data tier allocation section */}
|
||||
<DataTierAllocationField
|
||||
description={i18nTexts.dataTierAllocation.description}
|
||||
phase={'cold'}
|
||||
/>
|
||||
|
||||
{/* Freeze section */}
|
||||
{!isUsingSearchableSnapshotInHotPhase && (
|
||||
<ToggleFieldWithDescribedFormRow
|
||||
title={
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeText"
|
||||
defaultMessage="Freeze"
|
||||
/>
|
||||
</h3>
|
||||
}
|
||||
description={
|
||||
<EuiTextColor color="subdued">
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeIndexExplanationText"
|
||||
defaultMessage="Make the index read-only and minimize its memory footprint."
|
||||
/>{' '}
|
||||
<LearnMoreLink docPath="ilm-freeze.html" />
|
||||
</EuiTextColor>
|
||||
}
|
||||
fullWidth
|
||||
titleSize="xs"
|
||||
switchProps={{
|
||||
'data-test-subj': 'freezeSwitch',
|
||||
path: '_meta.cold.freezeEnabled',
|
||||
}}
|
||||
>
|
||||
<div />
|
||||
</ToggleFieldWithDescribedFormRow>
|
||||
)}
|
||||
{/* Data tier allocation section */}
|
||||
<DataTierAllocationField
|
||||
description={i18nTexts.dataTierAllocation.description}
|
||||
phase={coldProperty}
|
||||
/>
|
||||
<SetPriorityInputField phase={coldProperty} />
|
||||
</EuiAccordion>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
<IndexPriorityField phase={'cold'} />
|
||||
</Phase>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ import { useFormData, UseField, ToggleField } from '../../../../../../shared_imp
|
|||
|
||||
import { ActiveBadge, LearnMoreLink, OptionalLabel } from '../../index';
|
||||
|
||||
import { MinAgeInputField, SnapshotPoliciesField } from '../shared_fields';
|
||||
import { MinAgeField, SnapshotPoliciesField } from '../shared_fields';
|
||||
|
||||
const formFieldPaths = {
|
||||
enabled: '_meta.delete.enabled',
|
||||
|
@ -63,7 +63,7 @@ export const DeletePhase: FunctionComponent = () => {
|
|||
}
|
||||
fullWidth
|
||||
>
|
||||
{enabled && <MinAgeInputField phase="delete" />}
|
||||
{enabled && <MinAgeField phase="delete" />}
|
||||
</EuiDescribedFormGroup>
|
||||
{enabled ? (
|
||||
<EuiDescribedFormGroup
|
||||
|
|
|
@ -12,16 +12,12 @@ import {
|
|||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiSpacer,
|
||||
EuiDescribedFormGroup,
|
||||
EuiCallOut,
|
||||
EuiAccordion,
|
||||
EuiTextColor,
|
||||
EuiSwitch,
|
||||
EuiIconTip,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { Phases } from '../../../../../../../common/types';
|
||||
|
||||
import { useFormData, UseField, SelectField, NumericField } from '../../../../../../shared_imports';
|
||||
|
||||
import { i18nTexts } from '../../../i18n_texts';
|
||||
|
@ -32,20 +28,19 @@ import { useEditPolicyContext } from '../../../edit_policy_context';
|
|||
|
||||
import { ROLLOVER_FORM_PATHS, isUsingDefaultRolloverPath } from '../../../constants';
|
||||
|
||||
import { LearnMoreLink, ActiveBadge, DescribedFormRow } from '../../';
|
||||
import { LearnMoreLink, DescribedFormRow } from '../../';
|
||||
|
||||
import {
|
||||
ForcemergeField,
|
||||
SetPriorityInputField,
|
||||
IndexPriorityField,
|
||||
SearchableSnapshotField,
|
||||
ReadonlyField,
|
||||
ShrinkField,
|
||||
} from '../shared_fields';
|
||||
|
||||
import { Phase } from '../phase';
|
||||
import { maxSizeStoredUnits, maxAgeUnits } from './constants';
|
||||
|
||||
const hotProperty: keyof Phases = 'hot';
|
||||
|
||||
export const HotPhase: FunctionComponent = () => {
|
||||
const { license } = useEditPolicyContext();
|
||||
const [formData] = useFormData({
|
||||
|
@ -56,245 +51,210 @@ export const HotPhase: FunctionComponent = () => {
|
|||
const [showEmptyRolloverFieldsError, setShowEmptyRolloverFieldsError] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EuiDescribedFormGroup
|
||||
fullWidth
|
||||
titleSize="s"
|
||||
<Phase phase={'hot'}>
|
||||
<DescribedFormRow
|
||||
title={
|
||||
<div>
|
||||
<h2 className="eui-displayInlineBlock eui-alignMiddle">
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseLabel"
|
||||
defaultMessage="Hot phase"
|
||||
/>
|
||||
</h2>{' '}
|
||||
<ActiveBadge />
|
||||
</div>
|
||||
<h3>
|
||||
{i18n.translate('xpack.indexLifecycleMgmt.hotPhase.rolloverFieldTitle', {
|
||||
defaultMessage: 'Rollover',
|
||||
})}
|
||||
</h3>
|
||||
}
|
||||
description={
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseDescriptionMessage"
|
||||
defaultMessage="This phase is required. You are actively querying and
|
||||
writing to your index. For faster updates, you can roll over the index when it gets too big or too old."
|
||||
/>
|
||||
</p>
|
||||
}
|
||||
>
|
||||
<div />
|
||||
</EuiDescribedFormGroup>
|
||||
|
||||
<EuiAccordion
|
||||
id="ilmHotPhaseAdvancedSettings"
|
||||
buttonContent={i18n.translate('xpack.indexLifecycleMgmt.hotPhase.advancedSettingsButton', {
|
||||
defaultMessage: 'Advanced settings',
|
||||
})}
|
||||
paddingSize="m"
|
||||
>
|
||||
<DescribedFormRow
|
||||
title={
|
||||
<h3>
|
||||
{i18n.translate('xpack.indexLifecycleMgmt.hotPhase.rolloverFieldTitle', {
|
||||
defaultMessage: 'Rollover',
|
||||
})}
|
||||
</h3>
|
||||
}
|
||||
description={
|
||||
<>
|
||||
<EuiTextColor color="subdued">
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.hotPhase.rolloverDescriptionMessage"
|
||||
defaultMessage="Automate rollover of time series data for efficient storage and higher performance."
|
||||
/>{' '}
|
||||
<LearnMoreLink
|
||||
text={
|
||||
<>
|
||||
<EuiTextColor color="subdued">
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.hotPhase.rolloverDescriptionMessage"
|
||||
defaultMessage="Automate rollover of time series data for efficient storage and higher performance."
|
||||
/>{' '}
|
||||
<LearnMoreLink
|
||||
text={
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.hotPhase.learnAboutRolloverLinkText"
|
||||
defaultMessage="Learn more"
|
||||
/>
|
||||
}
|
||||
docPath="ilm-rollover.html"
|
||||
/>
|
||||
</p>
|
||||
</EuiTextColor>
|
||||
<EuiSpacer />
|
||||
<UseField<boolean> path={isUsingDefaultRolloverPath}>
|
||||
{(field) => (
|
||||
<>
|
||||
<EuiSwitch
|
||||
label={field.label}
|
||||
checked={field.value}
|
||||
onChange={(e) => field.setValue(e.target.checked)}
|
||||
data-test-subj="useDefaultRolloverSwitch"
|
||||
/>
|
||||
|
||||
<EuiIconTip
|
||||
type="questionInCircle"
|
||||
content={
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.hotPhase.learnAboutRolloverLinkText"
|
||||
defaultMessage="Learn more"
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.hotPhase.rolloverDefaultsTipContent"
|
||||
defaultMessage="Rollover when an index is 30 days old or reaches 50 gigabytes."
|
||||
/>
|
||||
}
|
||||
docPath="ilm-rollover.html"
|
||||
/>
|
||||
</p>
|
||||
</EuiTextColor>
|
||||
<EuiSpacer />
|
||||
<UseField<boolean> path={isUsingDefaultRolloverPath}>
|
||||
{(field) => (
|
||||
<>
|
||||
<EuiSwitch
|
||||
label={field.label}
|
||||
checked={field.value}
|
||||
onChange={(e) => field.setValue(e.target.checked)}
|
||||
data-test-subj="useDefaultRolloverSwitch"
|
||||
/>
|
||||
|
||||
<EuiIconTip
|
||||
type="questionInCircle"
|
||||
content={
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.hotPhase.rolloverDefaultsTipContent"
|
||||
defaultMessage="Rollover when an index is 30 days old or reaches 50 gigabytes."
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</UseField>
|
||||
</>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
{isUsingDefaultRollover === false ? (
|
||||
<div aria-live="polite" role="region">
|
||||
<UseField<boolean> path="_meta.hot.customRollover.enabled">
|
||||
{(field) => (
|
||||
<>
|
||||
<EuiSwitch
|
||||
label={field.label}
|
||||
checked={field.value}
|
||||
onChange={(e) => field.setValue(e.target.checked)}
|
||||
data-test-subj="rolloverSwitch"
|
||||
/>
|
||||
|
||||
<EuiIconTip
|
||||
type="questionInCircle"
|
||||
content={
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.hotPhase.enableRolloverTipContent"
|
||||
defaultMessage="Roll over to a new index when the
|
||||
current index meets one of the defined conditions."
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</UseField>
|
||||
{isUsingRollover && (
|
||||
<>
|
||||
<EuiSpacer size="m" />
|
||||
{showEmptyRolloverFieldsError && (
|
||||
<>
|
||||
<EuiCallOut
|
||||
title={i18nTexts.editPolicy.errors.rollOverConfigurationCallout.title}
|
||||
data-test-subj="rolloverSettingsRequired"
|
||||
color="danger"
|
||||
>
|
||||
<div>{i18nTexts.editPolicy.errors.rollOverConfigurationCallout.body}</div>
|
||||
</EuiCallOut>
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
)}
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem style={{ maxWidth: 188 }}>
|
||||
<UseField path={ROLLOVER_FORM_PATHS.maxSize}>
|
||||
{(field) => {
|
||||
const showErrorCallout = field.errors.some(
|
||||
(e) => e.code === ROLLOVER_EMPTY_VALIDATION
|
||||
);
|
||||
if (showErrorCallout !== showEmptyRolloverFieldsError) {
|
||||
setShowEmptyRolloverFieldsError(showErrorCallout);
|
||||
}
|
||||
return (
|
||||
<NumericField
|
||||
field={field}
|
||||
euiFieldProps={{
|
||||
'data-test-subj': `${hotProperty}-selectedMaxSizeStored`,
|
||||
min: 1,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</UseField>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={{ maxWidth: 188 }}>
|
||||
<UseField
|
||||
key="_meta.hot.customRollover.maxStorageSizeUnit"
|
||||
path="_meta.hot.customRollover.maxStorageSizeUnit"
|
||||
component={SelectField}
|
||||
componentProps={{
|
||||
'data-test-subj': `${hotProperty}-selectedMaxSizeStoredUnits`,
|
||||
hasEmptyLabelSpace: true,
|
||||
euiFieldProps: {
|
||||
options: maxSizeStoredUnits,
|
||||
'aria-label': i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.hotPhase.maximumIndexSizeUnitsAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Maximum index size units',
|
||||
}
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem style={{ maxWidth: 188 }}>
|
||||
<UseField
|
||||
path={ROLLOVER_FORM_PATHS.maxDocs}
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${hotProperty}-selectedMaxDocuments`,
|
||||
min: 1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem style={{ maxWidth: 188 }}>
|
||||
<UseField
|
||||
path={ROLLOVER_FORM_PATHS.maxAge}
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${hotProperty}-selectedMaxAge`,
|
||||
min: 1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={{ maxWidth: 188 }}>
|
||||
<UseField
|
||||
key="_meta.hot.customRollover.maxAgeUnit"
|
||||
path="_meta.hot.customRollover.maxAgeUnit"
|
||||
component={SelectField}
|
||||
componentProps={{
|
||||
'data-test-subj': `${hotProperty}-selectedMaxAgeUnits`,
|
||||
hasEmptyLabelSpace: true,
|
||||
euiFieldProps: {
|
||||
'aria-label': i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.hotPhase.maximumAgeUnitsAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Maximum age units',
|
||||
}
|
||||
),
|
||||
options: maxAgeUnits,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
</DescribedFormRow>
|
||||
{isUsingRollover && (
|
||||
<>
|
||||
{<ForcemergeField phase="hot" />}
|
||||
<ShrinkField phase="hot" />
|
||||
{license.canUseSearchableSnapshot() && <SearchableSnapshotField phase="hot" />}
|
||||
<ReadonlyField phase={'hot'} />
|
||||
</UseField>
|
||||
</>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
{isUsingDefaultRollover === false ? (
|
||||
<div aria-live="polite" role="region">
|
||||
<UseField<boolean> path="_meta.hot.customRollover.enabled">
|
||||
{(field) => (
|
||||
<>
|
||||
<EuiSwitch
|
||||
label={field.label}
|
||||
checked={field.value}
|
||||
onChange={(e) => field.setValue(e.target.checked)}
|
||||
data-test-subj="rolloverSwitch"
|
||||
/>
|
||||
|
||||
<EuiIconTip
|
||||
type="questionInCircle"
|
||||
content={
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.hotPhase.enableRolloverTipContent"
|
||||
defaultMessage="Roll over to a new index when the
|
||||
current index meets one of the defined conditions."
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</UseField>
|
||||
{isUsingRollover && (
|
||||
<>
|
||||
<EuiSpacer size="m" />
|
||||
{showEmptyRolloverFieldsError && (
|
||||
<>
|
||||
<EuiCallOut
|
||||
title={i18nTexts.editPolicy.errors.rollOverConfigurationCallout.title}
|
||||
data-test-subj="rolloverSettingsRequired"
|
||||
color="danger"
|
||||
>
|
||||
<div>{i18nTexts.editPolicy.errors.rollOverConfigurationCallout.body}</div>
|
||||
</EuiCallOut>
|
||||
<EuiSpacer size="s" />
|
||||
</>
|
||||
)}
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem style={{ maxWidth: 188 }}>
|
||||
<UseField path={ROLLOVER_FORM_PATHS.maxSize}>
|
||||
{(field) => {
|
||||
const showErrorCallout = field.errors.some(
|
||||
(e) => e.code === ROLLOVER_EMPTY_VALIDATION
|
||||
);
|
||||
if (showErrorCallout !== showEmptyRolloverFieldsError) {
|
||||
setShowEmptyRolloverFieldsError(showErrorCallout);
|
||||
}
|
||||
return (
|
||||
<NumericField
|
||||
field={field}
|
||||
euiFieldProps={{
|
||||
'data-test-subj': `hot-selectedMaxSizeStored`,
|
||||
min: 1,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</UseField>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={{ maxWidth: 188 }}>
|
||||
<UseField
|
||||
key="_meta.hot.customRollover.maxStorageSizeUnit"
|
||||
path="_meta.hot.customRollover.maxStorageSizeUnit"
|
||||
component={SelectField}
|
||||
componentProps={{
|
||||
'data-test-subj': `hot-selectedMaxSizeStoredUnits`,
|
||||
hasEmptyLabelSpace: true,
|
||||
euiFieldProps: {
|
||||
options: maxSizeStoredUnits,
|
||||
'aria-label': i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.hotPhase.maximumIndexSizeUnitsAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Maximum index size units',
|
||||
}
|
||||
),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem style={{ maxWidth: 188 }}>
|
||||
<UseField
|
||||
path={ROLLOVER_FORM_PATHS.maxDocs}
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `hot-selectedMaxDocuments`,
|
||||
min: 1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem style={{ maxWidth: 188 }}>
|
||||
<UseField
|
||||
path={ROLLOVER_FORM_PATHS.maxAge}
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `hot-selectedMaxAge`,
|
||||
min: 1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={{ maxWidth: 188 }}>
|
||||
<UseField
|
||||
key="_meta.hot.customRollover.maxAgeUnit"
|
||||
path="_meta.hot.customRollover.maxAgeUnit"
|
||||
component={SelectField}
|
||||
componentProps={{
|
||||
'data-test-subj': `hot-selectedMaxAgeUnits`,
|
||||
hasEmptyLabelSpace: true,
|
||||
euiFieldProps: {
|
||||
'aria-label': i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.hotPhase.maximumAgeUnitsAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Maximum age units',
|
||||
}
|
||||
),
|
||||
options: maxAgeUnits,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div />
|
||||
)}
|
||||
<SetPriorityInputField phase={hotProperty} />
|
||||
</EuiAccordion>
|
||||
</>
|
||||
</DescribedFormRow>
|
||||
{isUsingRollover && (
|
||||
<>
|
||||
{<ForcemergeField phase={'hot'} />}
|
||||
<ShrinkField phase={'hot'} />
|
||||
{license.canUseSearchableSnapshot() && <SearchableSnapshotField phase={'hot'} />}
|
||||
<ReadonlyField phase={'hot'} />
|
||||
</>
|
||||
)}
|
||||
<IndexPriorityField phase={'hot'} />
|
||||
</Phase>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -11,3 +11,5 @@ export { WarmPhase } from './warm_phase';
|
|||
export { ColdPhase } from './cold_phase';
|
||||
|
||||
export { DeletePhase } from './delete_phase';
|
||||
|
||||
export { Phase } from './phase';
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FunctionComponent, useState } from 'react';
|
||||
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiPanel,
|
||||
EuiTitle,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
EuiButtonEmpty,
|
||||
} from '@elastic/eui';
|
||||
import { get } from 'lodash';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
import { ToggleField, UseField, useFormData } from '../../../../../shared_imports';
|
||||
import { i18nTexts } from '../../i18n_texts';
|
||||
|
||||
import { ActiveHighlight } from '../active_highlight';
|
||||
import { MinAgeField } from './shared_fields';
|
||||
|
||||
interface Props {
|
||||
phase: 'hot' | 'warm' | 'cold';
|
||||
}
|
||||
|
||||
export const Phase: FunctionComponent<Props> = ({ children, phase }) => {
|
||||
const enabledPath = `_meta.${phase}.enabled`;
|
||||
const [formData] = useFormData({
|
||||
watch: [enabledPath],
|
||||
});
|
||||
|
||||
// hot phase is always enabled
|
||||
const enabled = get(formData, enabledPath) || phase === 'hot';
|
||||
|
||||
const [isShowingSettings, setShowingSettings] = useState<boolean>(false);
|
||||
return (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
<ActiveHighlight phase={phase} enabled={enabled} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiPanel hasShadow={enabled}>
|
||||
<EuiFlexGroup wrap>
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup alignItems="center" gutterSize={'s'}>
|
||||
{phase !== 'hot' && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<UseField
|
||||
path={enabledPath}
|
||||
component={ToggleField}
|
||||
componentProps={{
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `enablePhaseSwitch-${phase}`,
|
||||
showLabel: false,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle size={'s'}>
|
||||
<h2>{i18nTexts.editPolicy.titles[phase]}</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
{enabled && (
|
||||
<EuiFlexItem>
|
||||
<EuiFlexGroup
|
||||
justifyContent="spaceBetween"
|
||||
alignItems="center"
|
||||
gutterSize={'xs'}
|
||||
wrap
|
||||
>
|
||||
<EuiFlexItem grow={true}>
|
||||
{phase !== 'hot' && <MinAgeField phase={phase} />}
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty
|
||||
data-test-subj={`${phase}-settingsSwitch`}
|
||||
onClick={() => {
|
||||
setShowingSettings(!isShowingSettings);
|
||||
}}
|
||||
size="xs"
|
||||
iconType="controlsVertical"
|
||||
iconSide="left"
|
||||
aria-controls={`${phase}-phaseContent`}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.phaseSettings.buttonLabel"
|
||||
defaultMessage="Settings"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
<EuiText color="subdued" size={'s'} style={{ maxWidth: '50%' }}>
|
||||
{i18nTexts.editPolicy.descriptions[phase]}
|
||||
</EuiText>
|
||||
|
||||
{enabled && (
|
||||
<div style={isShowingSettings ? {} : { display: 'none' }} id={`${phase}-phaseContent`}>
|
||||
<EuiSpacer />
|
||||
{children}
|
||||
</div>
|
||||
)}
|
||||
</EuiPanel>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
|
@ -6,9 +6,8 @@
|
|||
|
||||
import React, { useMemo } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { EuiSpacer, EuiTextColor } from '@elastic/eui';
|
||||
|
||||
import { UseField, ToggleField, NumericField } from '../../../../../../shared_imports';
|
||||
import { UseField, CheckBoxField, NumericField } from '../../../../../../shared_imports';
|
||||
|
||||
import { i18nTexts } from '../../../i18n_texts';
|
||||
|
||||
|
@ -38,50 +37,43 @@ export const ForcemergeField: React.FunctionComponent<Props> = ({ phase }) => {
|
|||
</h3>
|
||||
}
|
||||
description={
|
||||
<EuiTextColor color="subdued">
|
||||
<>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.forceMerge.enableExplanationText"
|
||||
defaultMessage="Reduce the number of segments in your shard by merging smaller files and clearing deleted ones."
|
||||
/>{' '}
|
||||
<LearnMoreLink docPath="ilm-forcemerge.html" />
|
||||
</EuiTextColor>
|
||||
</>
|
||||
}
|
||||
titleSize="xs"
|
||||
fullWidth
|
||||
switchProps={{
|
||||
'aria-label': i18nTexts.editPolicy.forceMergeEnabledFieldLabel,
|
||||
'data-test-subj': `${phase}-forceMergeSwitch`,
|
||||
'aria-controls': 'forcemergeContent',
|
||||
label: i18nTexts.editPolicy.forceMergeEnabledFieldLabel,
|
||||
'data-test-subj': `${phase}-forceMergeSwitch`,
|
||||
initialValue: initialToggleValue,
|
||||
}}
|
||||
>
|
||||
<EuiSpacer />
|
||||
<div id="forcemergeContent" aria-live="polite" role="region">
|
||||
<UseField
|
||||
key={`phases.${phase}.actions.forcemerge.max_num_segments`}
|
||||
path={`phases.${phase}.actions.forcemerge.max_num_segments`}
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${phase}-selectedForceMergeSegments`,
|
||||
min: 1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<UseField
|
||||
key={`_meta.${phase}.bestCompression`}
|
||||
path={`_meta.${phase}.bestCompression`}
|
||||
component={ToggleField}
|
||||
componentProps={{
|
||||
hasEmptyLabelSpace: true,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${phase}-bestCompression`,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<UseField
|
||||
path={`phases.${phase}.actions.forcemerge.max_num_segments`}
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${phase}-selectedForceMergeSegments`,
|
||||
min: 1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<UseField
|
||||
path={`_meta.${phase}.bestCompression`}
|
||||
component={CheckBoxField}
|
||||
componentProps={{
|
||||
hasEmptyLabelSpace: true,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${phase}-bestCompression`,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</DescribedFormRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -8,9 +8,7 @@ export { DataTierAllocationField } from './data_tier_allocation_field';
|
|||
|
||||
export { ForcemergeField } from './forcemerge_field';
|
||||
|
||||
export { SetPriorityInputField } from './set_priority_input_field';
|
||||
|
||||
export { MinAgeInputField } from './min_age_input_field';
|
||||
export { MinAgeField } from './min_age_field';
|
||||
|
||||
export { SnapshotPoliciesField } from './snapshot_policies_field';
|
||||
|
||||
|
@ -19,3 +17,7 @@ export { ShrinkField } from './shrink_field';
|
|||
export { SearchableSnapshotField } from './searchable_snapshot_field';
|
||||
|
||||
export { ReadonlyField } from './readonly_field';
|
||||
|
||||
export { ReplicasField } from './replicas_field';
|
||||
|
||||
export { IndexPriorityField } from './index_priority_field';
|
||||
|
|
|
@ -4,23 +4,32 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import React, { FunctionComponent, useMemo } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { EuiTextColor, EuiDescribedFormGroup } from '@elastic/eui';
|
||||
|
||||
import { Phases } from '../../../../../../../common/types';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiSpacer, EuiTextColor } from '@elastic/eui';
|
||||
|
||||
import { UseField, NumericField } from '../../../../../../shared_imports';
|
||||
|
||||
import { LearnMoreLink } from '../..';
|
||||
import { LearnMoreLink, DescribedFormRow } from '../..';
|
||||
import { useEditPolicyContext } from '../../../edit_policy_context';
|
||||
|
||||
interface Props {
|
||||
phase: keyof Phases & string;
|
||||
phase: 'hot' | 'warm' | 'cold';
|
||||
}
|
||||
|
||||
export const SetPriorityInputField: FunctionComponent<Props> = ({ phase }) => {
|
||||
export const IndexPriorityField: FunctionComponent<Props> = ({ phase }) => {
|
||||
const { policy, isNewPolicy } = useEditPolicyContext();
|
||||
|
||||
const initialToggleValue = useMemo<boolean>(() => {
|
||||
return (
|
||||
isNewPolicy || // enable index priority for new policies
|
||||
!policy.phases[phase]?.actions || // enable index priority for new phases
|
||||
policy.phases[phase]?.actions?.set_priority != null // enable index priority if it's set
|
||||
);
|
||||
}, [isNewPolicy, policy.phases, phase]);
|
||||
|
||||
return (
|
||||
<EuiDescribedFormGroup
|
||||
<DescribedFormRow
|
||||
title={
|
||||
<h3>
|
||||
<FormattedMessage
|
||||
|
@ -41,19 +50,27 @@ export const SetPriorityInputField: FunctionComponent<Props> = ({ phase }) => {
|
|||
}
|
||||
titleSize="xs"
|
||||
fullWidth
|
||||
switchProps={{
|
||||
label: i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.indexPriority.indexPriorityEnabledFieldLabel',
|
||||
{
|
||||
defaultMessage: 'Set index priority',
|
||||
}
|
||||
),
|
||||
'data-test-subj': `${phase}-indexPrioritySwitch`,
|
||||
initialValue: initialToggleValue,
|
||||
}}
|
||||
>
|
||||
<EuiSpacer />
|
||||
<UseField
|
||||
key={`phases.${phase}.actions.set_priority.priority`}
|
||||
path={`phases.${phase}.actions.set_priority.priority`}
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
euiFieldProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${phase}-phaseIndexPriority`,
|
||||
min: 0,
|
||||
},
|
||||
'data-test-subj': `${phase}-indexPriority`,
|
||||
min: 0,
|
||||
}}
|
||||
/>
|
||||
</EuiDescribedFormGroup>
|
||||
</DescribedFormRow>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export { MinAgeField } from './min_age_field';
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* 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 { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
import {
|
||||
EuiFieldNumber,
|
||||
EuiFieldNumberProps,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
EuiSelect,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { UseField, getFieldValidityAndErrorMessage } from '../../../../../../../shared_imports';
|
||||
|
||||
import { getUnitsAriaLabelForPhase, getTimingLabelForPhase } from './util';
|
||||
|
||||
type PhaseWithMinAgeAction = 'warm' | 'cold' | 'delete';
|
||||
|
||||
const i18nTexts = {
|
||||
daysOptionLabel: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.daysOptionLabel', {
|
||||
defaultMessage: 'days',
|
||||
}),
|
||||
|
||||
hoursOptionLabel: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.hoursOptionLabel', {
|
||||
defaultMessage: 'hours',
|
||||
}),
|
||||
minutesOptionLabel: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.minutesOptionLabel', {
|
||||
defaultMessage: 'minutes',
|
||||
}),
|
||||
|
||||
secondsOptionLabel: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.secondsOptionLabel', {
|
||||
defaultMessage: 'seconds',
|
||||
}),
|
||||
millisecondsOptionLabel: i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.milliSecondsOptionLabel',
|
||||
{
|
||||
defaultMessage: 'milliseconds',
|
||||
}
|
||||
),
|
||||
|
||||
microsecondsOptionLabel: i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.microSecondsOptionLabel',
|
||||
{
|
||||
defaultMessage: 'microseconds',
|
||||
}
|
||||
),
|
||||
|
||||
nanosecondsOptionLabel: i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.nanoSecondsOptionLabel',
|
||||
{
|
||||
defaultMessage: 'nanoseconds',
|
||||
}
|
||||
),
|
||||
};
|
||||
|
||||
interface Props {
|
||||
phase: PhaseWithMinAgeAction;
|
||||
}
|
||||
|
||||
export const MinAgeField: FunctionComponent<Props> = ({ phase }): React.ReactElement => {
|
||||
return (
|
||||
<UseField path={`phases.${phase}.min_age`}>
|
||||
{(field) => {
|
||||
const { isInvalid, errorMessage } = getFieldValidityAndErrorMessage(field);
|
||||
return (
|
||||
<EuiFormRow fullWidth isInvalid={isInvalid} error={errorMessage}>
|
||||
<EuiFlexGroup gutterSize={'s'} alignItems={'center'} justifyContent={'spaceBetween'}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText className={'eui-textNoWrap'} size={'xs'}>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.minimumAge.minimumAgeFieldLabel"
|
||||
defaultMessage="Move data into phase when:"
|
||||
/>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={true}>
|
||||
<EuiFlexGroup gutterSize={'s'}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFieldNumber
|
||||
style={{ minWidth: 50 }}
|
||||
compressed
|
||||
aria-label={getTimingLabelForPhase(phase)}
|
||||
isInvalid={isInvalid}
|
||||
value={field.value as EuiFieldNumberProps['value']}
|
||||
onChange={field.onChange}
|
||||
isLoading={field.isValidating}
|
||||
data-test-subj={`${phase}-selectedMinimumAge`}
|
||||
min={0}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={true} style={{ minWidth: 165 }}>
|
||||
<UseField path={`_meta.${phase}.minAgeUnit`}>
|
||||
{(unitField) => {
|
||||
const { isInvalid: isUnitFieldInvalid } = getFieldValidityAndErrorMessage(
|
||||
unitField
|
||||
);
|
||||
return (
|
||||
<EuiSelect
|
||||
compressed
|
||||
value={unitField.value as string}
|
||||
onChange={(e) => {
|
||||
unitField.setValue(e.target.value);
|
||||
}}
|
||||
isInvalid={isUnitFieldInvalid}
|
||||
append={'old'}
|
||||
data-test-subj={`${phase}-selectedMinimumAgeUnits`}
|
||||
aria-label={getUnitsAriaLabelForPhase(phase)}
|
||||
options={[
|
||||
{
|
||||
value: 'd',
|
||||
text: i18nTexts.daysOptionLabel,
|
||||
},
|
||||
{
|
||||
value: 'h',
|
||||
text: i18nTexts.hoursOptionLabel,
|
||||
},
|
||||
{
|
||||
value: 'm',
|
||||
text: i18nTexts.minutesOptionLabel,
|
||||
},
|
||||
{
|
||||
value: 's',
|
||||
text: i18nTexts.secondsOptionLabel,
|
||||
},
|
||||
{
|
||||
value: 'ms',
|
||||
text: i18nTexts.millisecondsOptionLabel,
|
||||
},
|
||||
{
|
||||
value: 'micros',
|
||||
text: i18nTexts.microsecondsOptionLabel,
|
||||
},
|
||||
{
|
||||
value: 'nanos',
|
||||
text: i18nTexts.nanosecondsOptionLabel,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</UseField>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFormRow>
|
||||
);
|
||||
}}
|
||||
</UseField>
|
||||
);
|
||||
};
|
|
@ -1,205 +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 { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
|
||||
import { UseField, NumericField, SelectField } from '../../../../../../../shared_imports';
|
||||
|
||||
import { LearnMoreLink } from '../../../learn_more_link';
|
||||
import { useConfigurationIssues } from '../../../../form';
|
||||
|
||||
import { getUnitsAriaLabelForPhase, getTimingLabelForPhase } from './util';
|
||||
|
||||
type PhaseWithMinAgeAction = 'warm' | 'cold' | 'delete';
|
||||
|
||||
interface Props {
|
||||
phase: PhaseWithMinAgeAction;
|
||||
}
|
||||
|
||||
export const MinAgeInputField: FunctionComponent<Props> = ({ phase }): React.ReactElement => {
|
||||
const { isUsingRollover: rolloverEnabled } = useConfigurationIssues();
|
||||
|
||||
let daysOptionLabel;
|
||||
let hoursOptionLabel;
|
||||
let minutesOptionLabel;
|
||||
let secondsOptionLabel;
|
||||
let millisecondsOptionLabel;
|
||||
let microsecondsOptionLabel;
|
||||
let nanosecondsOptionLabel;
|
||||
|
||||
if (rolloverEnabled) {
|
||||
daysOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.rolloverDaysOptionLabel',
|
||||
{
|
||||
defaultMessage: 'days from rollover',
|
||||
}
|
||||
);
|
||||
|
||||
hoursOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.rolloverHoursOptionLabel',
|
||||
{
|
||||
defaultMessage: 'hours from rollover',
|
||||
}
|
||||
);
|
||||
minutesOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.rolloverMinutesOptionLabel',
|
||||
{
|
||||
defaultMessage: 'minutes from rollover',
|
||||
}
|
||||
);
|
||||
|
||||
secondsOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.rolloverSecondsOptionLabel',
|
||||
{
|
||||
defaultMessage: 'seconds from rollover',
|
||||
}
|
||||
);
|
||||
millisecondsOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.rolloverMilliSecondsOptionLabel',
|
||||
{
|
||||
defaultMessage: 'milliseconds from rollover',
|
||||
}
|
||||
);
|
||||
|
||||
microsecondsOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.rolloverMicroSecondsOptionLabel',
|
||||
{
|
||||
defaultMessage: 'microseconds from rollover',
|
||||
}
|
||||
);
|
||||
|
||||
nanosecondsOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.rolloverNanoSecondsOptionLabel',
|
||||
{
|
||||
defaultMessage: 'nanoseconds from rollover',
|
||||
}
|
||||
);
|
||||
} else {
|
||||
daysOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.creationDaysOptionLabel',
|
||||
{
|
||||
defaultMessage: 'days from index creation',
|
||||
}
|
||||
);
|
||||
|
||||
hoursOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.creationHoursOptionLabel',
|
||||
{
|
||||
defaultMessage: 'hours from index creation',
|
||||
}
|
||||
);
|
||||
|
||||
minutesOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.creationMinutesOptionLabel',
|
||||
{
|
||||
defaultMessage: 'minutes from index creation',
|
||||
}
|
||||
);
|
||||
|
||||
secondsOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.creationSecondsOptionLabel',
|
||||
{
|
||||
defaultMessage: 'seconds from index creation',
|
||||
}
|
||||
);
|
||||
|
||||
millisecondsOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.creationMilliSecondsOptionLabel',
|
||||
{
|
||||
defaultMessage: 'milliseconds from index creation',
|
||||
}
|
||||
);
|
||||
|
||||
microsecondsOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.creationMicroSecondsOptionLabel',
|
||||
{
|
||||
defaultMessage: 'microseconds from index creation',
|
||||
}
|
||||
);
|
||||
|
||||
nanosecondsOptionLabel = i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.creationNanoSecondsOptionLabel',
|
||||
{
|
||||
defaultMessage: 'nanoseconds from index creation',
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem style={{ maxWidth: 140 }}>
|
||||
<UseField
|
||||
path={`phases.${phase}.min_age`}
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
label: getTimingLabelForPhase(phase),
|
||||
helpText: (
|
||||
<LearnMoreLink
|
||||
docPath="ilm-index-lifecycle.html#ilm-phase-transitions"
|
||||
text={
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.learnAboutTimingText"
|
||||
defaultMessage="Learn about timing"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
),
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${phase}-selectedMinimumAge`,
|
||||
min: 0,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem style={{ maxWidth: 236 }}>
|
||||
<UseField
|
||||
path={`_meta.${phase}.minAgeUnit`}
|
||||
component={SelectField}
|
||||
componentProps={{
|
||||
hasEmptyLabelSpace: true,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${phase}-selectedMinimumAgeUnits`,
|
||||
'aria-label': getUnitsAriaLabelForPhase(phase),
|
||||
options: [
|
||||
{
|
||||
value: 'd',
|
||||
text: daysOptionLabel,
|
||||
},
|
||||
{
|
||||
value: 'h',
|
||||
text: hoursOptionLabel,
|
||||
},
|
||||
{
|
||||
value: 'm',
|
||||
text: minutesOptionLabel,
|
||||
},
|
||||
{
|
||||
value: 's',
|
||||
text: secondsOptionLabel,
|
||||
},
|
||||
{
|
||||
value: 'ms',
|
||||
text: millisecondsOptionLabel,
|
||||
},
|
||||
{
|
||||
value: 'micros',
|
||||
text: microsecondsOptionLabel,
|
||||
},
|
||||
{
|
||||
value: 'nanos',
|
||||
text: nanosecondsOptionLabel,
|
||||
},
|
||||
],
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* 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 { UseField, NumericField } from '../../../../../../shared_imports';
|
||||
import { useEditPolicyContext } from '../../../edit_policy_context';
|
||||
import { DescribedFormRow } from '../../described_form_row';
|
||||
|
||||
interface Props {
|
||||
phase: 'warm' | 'cold';
|
||||
}
|
||||
|
||||
export const ReplicasField: FunctionComponent<Props> = ({ phase }) => {
|
||||
const { policy } = useEditPolicyContext();
|
||||
const initialValue = policy.phases[phase]?.actions?.allocate?.number_of_replicas != null;
|
||||
return (
|
||||
<DescribedFormRow
|
||||
title={
|
||||
<h3>
|
||||
{i18n.translate('xpack.indexLifecycleMgmt.numberOfReplicas.formRowTitle', {
|
||||
defaultMessage: 'Replicas',
|
||||
})}
|
||||
</h3>
|
||||
}
|
||||
description={i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.numberOfReplicas.formRowDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Set the number of replicas. Remains the same as the previous phase by default.',
|
||||
}
|
||||
)}
|
||||
switchProps={{
|
||||
'data-test-subj': `${phase}-setReplicasSwitch`,
|
||||
label: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.numberOfReplicas.switchLabel', {
|
||||
defaultMessage: 'Set replicas',
|
||||
}),
|
||||
initialValue,
|
||||
}}
|
||||
fullWidth
|
||||
>
|
||||
<UseField
|
||||
path={`phases.${phase}.actions.allocate.number_of_replicas`}
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${phase}-selectedReplicaCount`,
|
||||
min: 0,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</DescribedFormRow>
|
||||
);
|
||||
};
|
|
@ -42,32 +42,28 @@ export const ShrinkField: FunctionComponent<Props> = ({ phase }) => {
|
|||
}
|
||||
titleSize="xs"
|
||||
switchProps={{
|
||||
'aria-controls': 'shrinkContent',
|
||||
'data-test-subj': `${phase}-shrinkSwitch`,
|
||||
label: i18nTexts.editPolicy.shrinkLabel,
|
||||
'aria-label': i18nTexts.editPolicy.shrinkLabel,
|
||||
initialValue: Boolean(policy.phases[phase]?.actions?.shrink),
|
||||
}}
|
||||
fullWidth
|
||||
>
|
||||
<div id="shrinkContent" aria-live="polite" role="region">
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<UseField
|
||||
path={path}
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${phase}-selectedPrimaryShardCount`,
|
||||
min: 1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
</div>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem>
|
||||
<UseField
|
||||
path={path}
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${phase}-primaryShardCount`,
|
||||
min: 1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer />
|
||||
</DescribedFormRow>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -5,30 +5,21 @@
|
|||
*/
|
||||
|
||||
import React, { FunctionComponent } from 'react';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { get } from 'lodash';
|
||||
|
||||
import { EuiSpacer, EuiDescribedFormGroup, EuiAccordion } from '@elastic/eui';
|
||||
|
||||
import { useFormData, UseField, ToggleField, NumericField } from '../../../../../../shared_imports';
|
||||
|
||||
import { Phases } from '../../../../../../../common/types';
|
||||
|
||||
import { useEditPolicyContext } from '../../../edit_policy_context';
|
||||
import { useConfigurationIssues } from '../../../form';
|
||||
|
||||
import { ActiveBadge, DescribedFormRow } from '../../';
|
||||
|
||||
import {
|
||||
MinAgeInputField,
|
||||
ForcemergeField,
|
||||
SetPriorityInputField,
|
||||
IndexPriorityField,
|
||||
DataTierAllocationField,
|
||||
ShrinkField,
|
||||
ReadonlyField,
|
||||
ReplicasField,
|
||||
} from '../shared_fields';
|
||||
|
||||
import { Phase } from '../phase';
|
||||
|
||||
const i18nTexts = {
|
||||
dataTierAllocation: {
|
||||
description: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.description', {
|
||||
|
@ -37,153 +28,26 @@ const i18nTexts = {
|
|||
},
|
||||
};
|
||||
|
||||
const warmProperty: keyof Phases = 'warm';
|
||||
|
||||
const formFieldPaths = {
|
||||
enabled: '_meta.warm.enabled',
|
||||
warmPhaseOnRollover: '_meta.warm.warmPhaseOnRollover',
|
||||
};
|
||||
|
||||
export const WarmPhase: FunctionComponent = () => {
|
||||
const { policy } = useEditPolicyContext();
|
||||
const { isUsingSearchableSnapshotInHotPhase, isUsingRollover } = useConfigurationIssues();
|
||||
const [formData] = useFormData({
|
||||
watch: [formFieldPaths.enabled, formFieldPaths.warmPhaseOnRollover],
|
||||
});
|
||||
|
||||
const enabled = get(formData, formFieldPaths.enabled);
|
||||
const warmPhaseOnRollover = get(formData, formFieldPaths.warmPhaseOnRollover);
|
||||
const { isUsingSearchableSnapshotInHotPhase } = useConfigurationIssues();
|
||||
|
||||
return (
|
||||
<div id="warmPhaseContent" aria-live="polite" role="region" aria-relevant="additions">
|
||||
<>
|
||||
<EuiDescribedFormGroup
|
||||
title={
|
||||
<div>
|
||||
<h2 className="eui-displayInlineBlock eui-alignMiddle">
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseLabel"
|
||||
defaultMessage="Warm phase"
|
||||
/>
|
||||
</h2>{' '}
|
||||
{enabled && <ActiveBadge />}
|
||||
</div>
|
||||
}
|
||||
titleSize="s"
|
||||
description={
|
||||
<>
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseDescriptionMessage"
|
||||
defaultMessage="You are still querying your index, but it is read-only.
|
||||
You can allocate shards to less performant hardware.
|
||||
For faster searches, you can reduce the number of shards and force merge segments."
|
||||
/>
|
||||
</p>
|
||||
<UseField
|
||||
path={formFieldPaths.enabled}
|
||||
component={ToggleField}
|
||||
componentProps={{
|
||||
euiFieldProps: {
|
||||
'data-test-subj': 'enablePhaseSwitch-warm',
|
||||
'aria-controls': 'warmPhaseContent',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
fullWidth
|
||||
>
|
||||
<>
|
||||
{enabled && (
|
||||
<>
|
||||
{isUsingRollover && (
|
||||
<UseField
|
||||
path={formFieldPaths.warmPhaseOnRollover}
|
||||
component={ToggleField}
|
||||
componentProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${warmProperty}-warmPhaseOnRollover`,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{(!warmPhaseOnRollover || !isUsingRollover) && (
|
||||
<>
|
||||
<EuiSpacer size="m" />
|
||||
<MinAgeInputField phase="warm" />
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
</EuiDescribedFormGroup>
|
||||
<Phase phase={'warm'}>
|
||||
<ReplicasField phase={'warm'} />
|
||||
|
||||
{enabled && (
|
||||
<EuiAccordion
|
||||
id="ilmWarmPhaseAdvancedSettings"
|
||||
buttonContent={i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.warmPhase.advancedSettingsButton',
|
||||
{
|
||||
defaultMessage: 'Advanced settings',
|
||||
}
|
||||
)}
|
||||
paddingSize="m"
|
||||
>
|
||||
<DescribedFormRow
|
||||
title={
|
||||
<h3>
|
||||
{i18n.translate('xpack.indexLifecycleMgmt.warmPhase.replicasTitle', {
|
||||
defaultMessage: 'Replicas',
|
||||
})}
|
||||
</h3>
|
||||
}
|
||||
description={i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Set the number of replicas. Remains the same as the previous phase by default.',
|
||||
}
|
||||
)}
|
||||
switchProps={{
|
||||
'data-test-subj': 'warm-setReplicasSwitch',
|
||||
label: i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.warmPhase.numberOfReplicas.switchLabel',
|
||||
{ defaultMessage: 'Set replicas' }
|
||||
),
|
||||
initialValue: policy.phases.warm?.actions?.allocate?.number_of_replicas != null,
|
||||
}}
|
||||
fullWidth
|
||||
>
|
||||
<UseField
|
||||
path="phases.warm.actions.allocate.number_of_replicas"
|
||||
component={NumericField}
|
||||
componentProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': `${warmProperty}-selectedReplicaCount`,
|
||||
min: 0,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</DescribedFormRow>
|
||||
{!isUsingSearchableSnapshotInHotPhase && <ShrinkField phase={'warm'} />}
|
||||
|
||||
{!isUsingSearchableSnapshotInHotPhase && <ShrinkField phase="warm" />}
|
||||
{!isUsingSearchableSnapshotInHotPhase && <ForcemergeField phase={'warm'} />}
|
||||
|
||||
{!isUsingSearchableSnapshotInHotPhase && <ForcemergeField phase="warm" />}
|
||||
<ReadonlyField phase={'warm'} />
|
||||
|
||||
<ReadonlyField phase={'warm'} />
|
||||
{/* Data tier allocation section */}
|
||||
<DataTierAllocationField
|
||||
description={i18nTexts.dataTierAllocation.description}
|
||||
phase={'warm'}
|
||||
/>
|
||||
|
||||
{/* Data tier allocation section */}
|
||||
<DataTierAllocationField
|
||||
description={i18nTexts.dataTierAllocation.description}
|
||||
phase={warmProperty}
|
||||
/>
|
||||
<SetPriorityInputField phase="warm" />
|
||||
</EuiAccordion>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
<IndexPriorityField phase={'warm'} />
|
||||
</Phase>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { Fragment, useEffect, useState, useMemo } from 'react';
|
||||
import React, { Fragment, useEffect, useMemo, useState } from 'react';
|
||||
import { get } from 'lodash';
|
||||
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
|
@ -16,7 +16,6 @@ import { i18n } from '@kbn/i18n';
|
|||
import {
|
||||
EuiButton,
|
||||
EuiButtonEmpty,
|
||||
EuiDescribedFormGroup,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiFormRow,
|
||||
|
@ -24,33 +23,35 @@ import {
|
|||
EuiPage,
|
||||
EuiPageBody,
|
||||
EuiPageContent,
|
||||
EuiPageContentHeader,
|
||||
EuiPageContentHeaderSection,
|
||||
EuiSpacer,
|
||||
EuiSwitch,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { useForm, UseField, TextField, useFormData } from '../../../shared_imports';
|
||||
import { TextField, UseField, useForm, useFormData } from '../../../shared_imports';
|
||||
|
||||
import { toasts } from '../../services/notification';
|
||||
|
||||
import { savePolicy } from './save_policy';
|
||||
|
||||
import {
|
||||
LearnMoreLink,
|
||||
PolicyJsonFlyout,
|
||||
ColdPhase,
|
||||
DeletePhase,
|
||||
HotPhase,
|
||||
PolicyJsonFlyout,
|
||||
WarmPhase,
|
||||
Timeline,
|
||||
} from './components';
|
||||
|
||||
import { schema, deserializer, createSerializer, createPolicyNameValidations, Form } from './form';
|
||||
import { createPolicyNameValidations, createSerializer, deserializer, Form, schema } from './form';
|
||||
|
||||
import { useEditPolicyContext } from './edit_policy_context';
|
||||
|
||||
import { FormInternal } from './types';
|
||||
import { createDocLink } from '../../services/documentation';
|
||||
|
||||
export interface Props {
|
||||
history: RouteComponentProps['history'];
|
||||
|
@ -75,7 +76,7 @@ export const EditPolicy: React.FunctionComponent<Props> = ({ history }) => {
|
|||
return createSerializer(isNewPolicy ? undefined : currentPolicy);
|
||||
}, [isNewPolicy, currentPolicy]);
|
||||
|
||||
const [saveAsNew, setSaveAsNew] = useState(isNewPolicy);
|
||||
const [saveAsNew, setSaveAsNew] = useState(false);
|
||||
const originalPolicyName: string = isNewPolicy ? '' : policyName!;
|
||||
|
||||
const { form } = useForm({
|
||||
|
@ -116,7 +117,7 @@ export const EditPolicy: React.FunctionComponent<Props> = ({ history }) => {
|
|||
);
|
||||
} else {
|
||||
const success = await savePolicy(
|
||||
{ ...policy, name: saveAsNew ? currentPolicyName : originalPolicyName },
|
||||
{ ...policy, name: saveAsNew || isNewPolicy ? currentPolicyName : originalPolicyName },
|
||||
isNewPolicy || saveAsNew
|
||||
);
|
||||
if (success) {
|
||||
|
@ -132,216 +133,187 @@ export const EditPolicy: React.FunctionComponent<Props> = ({ history }) => {
|
|||
return (
|
||||
<EuiPage>
|
||||
<EuiPageBody>
|
||||
<EuiPageContent
|
||||
className="ilmEditPolicyPageContent"
|
||||
verticalPosition="center"
|
||||
horizontalPosition="center"
|
||||
>
|
||||
<EuiTitle size="l" data-test-subj="policyTitle">
|
||||
<h1>
|
||||
{isNewPolicy
|
||||
? i18n.translate('xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage', {
|
||||
defaultMessage: 'Create an index lifecycle policy',
|
||||
})
|
||||
: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.editPolicyMessage', {
|
||||
defaultMessage: 'Edit index lifecycle policy {originalPolicyName}',
|
||||
values: { originalPolicyName },
|
||||
})}
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
|
||||
<div className="euiAnimateContentLoad">
|
||||
<Form form={form}>
|
||||
<EuiSpacer size="xs" />
|
||||
<EuiText color="subdued">
|
||||
<p>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.lifecyclePolicyDescriptionText"
|
||||
defaultMessage="Use an index policy to automate the four phases of the index lifecycle,
|
||||
from actively writing to the index to deleting it."
|
||||
/>{' '}
|
||||
<LearnMoreLink
|
||||
docPath="index-lifecycle-management.html"
|
||||
text={
|
||||
<EuiPageContent>
|
||||
<EuiPageContentHeader>
|
||||
<EuiPageContentHeaderSection>
|
||||
<EuiTitle size="l" data-test-subj="policyTitle">
|
||||
<h1>
|
||||
{isNewPolicy
|
||||
? i18n.translate('xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage', {
|
||||
defaultMessage: 'Create Policy',
|
||||
})
|
||||
: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.editPolicyMessage', {
|
||||
defaultMessage: 'Edit Policy {originalPolicyName}',
|
||||
values: { originalPolicyName },
|
||||
})}
|
||||
</h1>
|
||||
</EuiTitle>
|
||||
</EuiPageContentHeaderSection>
|
||||
<EuiPageContentHeaderSection>
|
||||
<EuiButtonEmpty
|
||||
href={createDocLink('index-lifecycle-management.html')}
|
||||
target="_blank"
|
||||
iconType="help"
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.documentationLinkText"
|
||||
defaultMessage="Documentation"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiPageContentHeaderSection>
|
||||
</EuiPageContentHeader>
|
||||
<Form form={form}>
|
||||
{isNewPolicy ? null : (
|
||||
<Fragment>
|
||||
<EuiText>
|
||||
<p>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.learnAboutIndexLifecycleManagementLinkText"
|
||||
defaultMessage="Learn about the index lifecycle."
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.editingExistingPolicyMessage"
|
||||
defaultMessage="You are editing an existing policy"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
|
||||
<EuiSpacer />
|
||||
|
||||
{isNewPolicy ? null : (
|
||||
<Fragment>
|
||||
<EuiText>
|
||||
<p>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.editingExistingPolicyMessage"
|
||||
defaultMessage="You are editing an existing policy"
|
||||
/>
|
||||
</strong>
|
||||
.{' '}
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.editingExistingPolicyExplanationMessage"
|
||||
defaultMessage="Any changes you make will affect the indices that are
|
||||
</strong>
|
||||
.{' '}
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.editingExistingPolicyExplanationMessage"
|
||||
defaultMessage="Any changes you make will affect the indices that are
|
||||
attached to this policy. Alternatively, you can save these changes in
|
||||
a new policy."
|
||||
/>
|
||||
</p>
|
||||
</EuiText>
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiFormRow>
|
||||
<EuiSwitch
|
||||
data-test-subj="saveAsNewSwitch"
|
||||
style={{ maxWidth: '100%' }}
|
||||
checked={saveAsNew}
|
||||
onChange={(e) => {
|
||||
setSaveAsNew(e.target.checked);
|
||||
}}
|
||||
label={
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.saveAsNewPolicyMessage"
|
||||
defaultMessage="Save as new policy"
|
||||
/>
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
</EuiFormRow>
|
||||
</Fragment>
|
||||
)}
|
||||
</p>
|
||||
</EuiText>
|
||||
<EuiSpacer />
|
||||
|
||||
{saveAsNew || isNewPolicy ? (
|
||||
<EuiDescribedFormGroup
|
||||
title={
|
||||
<div>
|
||||
<span className="eui-displayInlineBlock eui-alignMiddle">
|
||||
<EuiFormRow>
|
||||
<EuiSwitch
|
||||
data-test-subj="saveAsNewSwitch"
|
||||
style={{ maxWidth: '100%' }}
|
||||
checked={saveAsNew}
|
||||
onChange={(e) => {
|
||||
setSaveAsNew(e.target.checked);
|
||||
}}
|
||||
label={
|
||||
<span>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.nameLabel"
|
||||
defaultMessage="Name"
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.saveAsNewPolicyMessage"
|
||||
defaultMessage="Save as new policy"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
titleSize="s"
|
||||
fullWidth
|
||||
>
|
||||
<UseField<string, FormInternal>
|
||||
path={policyNamePath}
|
||||
config={{
|
||||
label: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.policyNameLabel', {
|
||||
defaultMessage: 'Policy name',
|
||||
}),
|
||||
helpText: i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.validPolicyNameMessage',
|
||||
{
|
||||
defaultMessage:
|
||||
'A policy name cannot start with an underscore and cannot contain a comma or a space.',
|
||||
}
|
||||
),
|
||||
validations: policyNameValidations,
|
||||
}}
|
||||
component={TextField}
|
||||
componentProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': 'policyNameField',
|
||||
},
|
||||
}}
|
||||
}
|
||||
/>
|
||||
</EuiDescribedFormGroup>
|
||||
) : null}
|
||||
</EuiFormRow>
|
||||
</Fragment>
|
||||
)}
|
||||
|
||||
<EuiHorizontalRule />
|
||||
{saveAsNew || isNewPolicy ? (
|
||||
<UseField<string, FormInternal>
|
||||
path={policyNamePath}
|
||||
config={{
|
||||
label: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.policyNameLabel', {
|
||||
defaultMessage: 'Policy name',
|
||||
}),
|
||||
helpText: i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.validPolicyNameMessage',
|
||||
{
|
||||
defaultMessage:
|
||||
'A policy name cannot start with an underscore and cannot contain a comma or a space.',
|
||||
}
|
||||
),
|
||||
validations: policyNameValidations,
|
||||
}}
|
||||
component={TextField}
|
||||
componentProps={{
|
||||
fullWidth: false,
|
||||
euiFieldProps: {
|
||||
'data-test-subj': 'policyNameField',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<Timeline />
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiSpacer size="l" />
|
||||
<Timeline />
|
||||
|
||||
<HotPhase />
|
||||
<EuiSpacer size="l" />
|
||||
|
||||
<EuiHorizontalRule />
|
||||
<HotPhase />
|
||||
|
||||
<WarmPhase />
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiHorizontalRule />
|
||||
<WarmPhase />
|
||||
|
||||
<ColdPhase />
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiHorizontalRule />
|
||||
<ColdPhase />
|
||||
|
||||
<DeletePhase />
|
||||
<EuiSpacer />
|
||||
|
||||
<EuiHorizontalRule />
|
||||
<DeletePhase />
|
||||
|
||||
<EuiFlexGroup justifyContent="spaceBetween">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
data-test-subj="savePolicyButton"
|
||||
fill
|
||||
iconType="check"
|
||||
iconSide="left"
|
||||
disabled={form.isValid === false || form.isSubmitting}
|
||||
onClick={submit}
|
||||
color="secondary"
|
||||
>
|
||||
{saveAsNew ? (
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.saveAsNewButton"
|
||||
defaultMessage="Save as new policy"
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.saveButton"
|
||||
defaultMessage="Save policy"
|
||||
/>
|
||||
)}
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty data-test-subj="cancelTestPolicy" onClick={backToPolicyList}>
|
||||
<EuiFlexGroup justifyContent="spaceBetween">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty onClick={togglePolicyJsonFlyout} data-test-subj="requestButton">
|
||||
{isShowingPolicyJsonFlyout ? (
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.hidePolicyJsonButto"
|
||||
defaultMessage="Hide request"
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.showPolicyJsonButto"
|
||||
defaultMessage="Show request"
|
||||
/>
|
||||
)}
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty data-test-subj="cancelTestPolicy" onClick={backToPolicyList}>
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.cancelButton"
|
||||
defaultMessage="Cancel"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButton
|
||||
data-test-subj="savePolicyButton"
|
||||
fill
|
||||
iconType="check"
|
||||
iconSide="left"
|
||||
disabled={form.isValid === false || form.isSubmitting}
|
||||
onClick={submit}
|
||||
>
|
||||
{saveAsNew ? (
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.cancelButton"
|
||||
defaultMessage="Cancel"
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.saveAsNewButton"
|
||||
defaultMessage="Save as new policy"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.saveButton"
|
||||
defaultMessage="Save policy"
|
||||
/>
|
||||
)}
|
||||
</EuiButton>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonEmpty onClick={togglePolicyJsonFlyout} data-test-subj="requestButton">
|
||||
{isShowingPolicyJsonFlyout ? (
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.hidePolicyJsonButto"
|
||||
defaultMessage="Hide request"
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="xpack.indexLifecycleMgmt.editPolicy.showPolicyJsonButto"
|
||||
defaultMessage="Show request"
|
||||
/>
|
||||
)}
|
||||
</EuiButtonEmpty>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
|
||||
{isShowingPolicyJsonFlyout ? (
|
||||
<PolicyJsonFlyout
|
||||
policyName={saveAsNew ? currentPolicyName : policyName}
|
||||
close={() => setIsShowingPolicyJsonFlyout(false)}
|
||||
/>
|
||||
) : null}
|
||||
</Form>
|
||||
</div>
|
||||
{isShowingPolicyJsonFlyout ? (
|
||||
<PolicyJsonFlyout
|
||||
policyName={saveAsNew ? currentPolicyName : policyName}
|
||||
close={() => setIsShowingPolicyJsonFlyout(false)}
|
||||
/>
|
||||
) : null}
|
||||
</Form>
|
||||
</EuiPageContent>
|
||||
</EuiPageBody>
|
||||
</EuiPage>
|
||||
|
|
|
@ -260,15 +260,6 @@ describe('deserializer and serializer', () => {
|
|||
expect(result.phases.hot!.actions.readonly).toBeUndefined();
|
||||
});
|
||||
|
||||
it('removes min_age from warm when rollover is enabled', () => {
|
||||
formInternal._meta.hot.customRollover.enabled = true;
|
||||
formInternal._meta.warm.warmPhaseOnRollover = true;
|
||||
|
||||
const result = serializer(formInternal);
|
||||
|
||||
expect(result.phases.warm!.min_age).toBeUndefined();
|
||||
});
|
||||
|
||||
it('adds default rollover configuration when enabled, but previously not configured', () => {
|
||||
delete formInternal.phases.hot!.actions.rollover;
|
||||
formInternal._meta.hot.isUsingDefaultRollover = true;
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { FormSchema, fieldValidators } from '../../../../shared_imports';
|
||||
import { defaultSetPriority, defaultPhaseIndexPriority } from '../../../constants';
|
||||
import { defaultIndexPriority } from '../../../constants';
|
||||
import { ROLLOVER_FORM_PATHS } from '../constants';
|
||||
|
||||
const rolloverFormPaths = Object.values(ROLLOVER_FORM_PATHS);
|
||||
|
||||
import { FormInternal } from '../types';
|
||||
|
||||
const rolloverFormPaths = Object.values(ROLLOVER_FORM_PATHS);
|
||||
|
||||
import {
|
||||
ifExistsNumberGreaterThanZero,
|
||||
ifExistsNumberNonNegative,
|
||||
|
@ -54,7 +54,6 @@ export const schema: FormSchema<FormInternal> = {
|
|||
},
|
||||
bestCompression: {
|
||||
label: i18nTexts.editPolicy.bestCompressionFieldLabel,
|
||||
helpText: i18nTexts.editPolicy.bestCompressionFieldHelpText,
|
||||
},
|
||||
readonlyEnabled: {
|
||||
defaultValue: false,
|
||||
|
@ -69,18 +68,11 @@ export const schema: FormSchema<FormInternal> = {
|
|||
{ defaultMessage: 'Activate warm phase' }
|
||||
),
|
||||
},
|
||||
warmPhaseOnRollover: {
|
||||
defaultValue: true,
|
||||
label: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.moveToWarmPhaseOnRolloverLabel', {
|
||||
defaultMessage: 'Move to warm phase on rollover',
|
||||
}),
|
||||
},
|
||||
minAgeUnit: {
|
||||
defaultValue: 'ms',
|
||||
},
|
||||
bestCompression: {
|
||||
label: i18nTexts.editPolicy.bestCompressionFieldLabel,
|
||||
helpText: i18nTexts.editPolicy.bestCompressionFieldHelpText,
|
||||
},
|
||||
dataTierAllocationType: {
|
||||
label: i18nTexts.editPolicy.allocationTypeOptionsFieldLabel,
|
||||
|
@ -218,9 +210,14 @@ export const schema: FormSchema<FormInternal> = {
|
|||
},
|
||||
set_priority: {
|
||||
priority: {
|
||||
defaultValue: defaultSetPriority as any,
|
||||
label: i18nTexts.editPolicy.setPriorityFieldLabel,
|
||||
validations: [{ validator: ifExistsNumberNonNegative }],
|
||||
defaultValue: defaultIndexPriority.hot as any,
|
||||
label: i18nTexts.editPolicy.indexPriorityFieldLabel,
|
||||
validations: [
|
||||
{
|
||||
validator: emptyField(i18nTexts.editPolicy.errors.numberRequired),
|
||||
},
|
||||
{ validator: ifExistsNumberNonNegative },
|
||||
],
|
||||
serializer: serializers.stringToNumber,
|
||||
},
|
||||
},
|
||||
|
@ -239,9 +236,12 @@ export const schema: FormSchema<FormInternal> = {
|
|||
allocate: {
|
||||
number_of_replicas: {
|
||||
label: i18n.translate('xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasLabel', {
|
||||
defaultMessage: 'Number of replicas (optional)',
|
||||
defaultMessage: 'Number of replicas',
|
||||
}),
|
||||
validations: [
|
||||
{
|
||||
validator: emptyField(i18nTexts.editPolicy.errors.numberRequired),
|
||||
},
|
||||
{
|
||||
validator: ifExistsNumberNonNegative,
|
||||
},
|
||||
|
@ -289,9 +289,14 @@ export const schema: FormSchema<FormInternal> = {
|
|||
},
|
||||
set_priority: {
|
||||
priority: {
|
||||
defaultValue: defaultPhaseIndexPriority as any,
|
||||
label: i18nTexts.editPolicy.setPriorityFieldLabel,
|
||||
validations: [{ validator: ifExistsNumberNonNegative }],
|
||||
defaultValue: defaultIndexPriority.warm as any,
|
||||
label: i18nTexts.editPolicy.indexPriorityFieldLabel,
|
||||
validations: [
|
||||
{
|
||||
validator: emptyField(i18nTexts.editPolicy.errors.numberRequired),
|
||||
},
|
||||
{ validator: ifExistsNumberNonNegative },
|
||||
],
|
||||
serializer: serializers.stringToNumber,
|
||||
},
|
||||
},
|
||||
|
@ -310,9 +315,12 @@ export const schema: FormSchema<FormInternal> = {
|
|||
allocate: {
|
||||
number_of_replicas: {
|
||||
label: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasLabel', {
|
||||
defaultMessage: 'Number of replicas (optional)',
|
||||
defaultMessage: 'Number of replicas',
|
||||
}),
|
||||
validations: [
|
||||
{
|
||||
validator: emptyField(i18nTexts.editPolicy.errors.numberRequired),
|
||||
},
|
||||
{
|
||||
validator: ifExistsNumberNonNegative,
|
||||
},
|
||||
|
@ -322,9 +330,14 @@ export const schema: FormSchema<FormInternal> = {
|
|||
},
|
||||
set_priority: {
|
||||
priority: {
|
||||
defaultValue: '0' as any,
|
||||
label: i18nTexts.editPolicy.setPriorityFieldLabel,
|
||||
validations: [{ validator: ifExistsNumberNonNegative }],
|
||||
defaultValue: defaultIndexPriority.cold as any,
|
||||
label: i18nTexts.editPolicy.indexPriorityFieldLabel,
|
||||
validations: [
|
||||
{
|
||||
validator: emptyField(i18nTexts.editPolicy.errors.numberRequired),
|
||||
},
|
||||
{ validator: ifExistsNumberNonNegative },
|
||||
],
|
||||
serializer: serializers.stringToNumber,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -20,9 +20,7 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => (
|
|||
): SerializedPolicy => {
|
||||
const { _meta, ...updatedPolicy } = data;
|
||||
|
||||
if (!updatedPolicy.phases || !updatedPolicy.phases.hot) {
|
||||
updatedPolicy.phases = { hot: { actions: {} } };
|
||||
}
|
||||
updatedPolicy.phases = { hot: { actions: {} }, ...updatedPolicy.phases };
|
||||
|
||||
return produce<SerializedPolicy>(originalPolicy ?? defaultPolicy, (draft) => {
|
||||
// Copy over all updated fields
|
||||
|
@ -32,7 +30,7 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => (
|
|||
* Important shared values for serialization
|
||||
*/
|
||||
const isUsingRollover = Boolean(
|
||||
_meta.hot.isUsingDefaultRollover || _meta.hot.customRollover.enabled
|
||||
_meta.hot?.isUsingDefaultRollover || _meta.hot?.customRollover.enabled
|
||||
);
|
||||
|
||||
// Next copy over all meta fields and delete any fields that have been removed
|
||||
|
@ -53,7 +51,7 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => (
|
|||
* HOT PHASE ROLLOVER
|
||||
*/
|
||||
if (isUsingRollover) {
|
||||
if (_meta.hot.isUsingDefaultRollover) {
|
||||
if (_meta.hot?.isUsingDefaultRollover) {
|
||||
hotPhaseActions.rollover = cloneDeep(defaultRolloverAction);
|
||||
} else {
|
||||
// Rollover may not exist if editing an existing policy with initially no rollover configured
|
||||
|
@ -63,7 +61,7 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => (
|
|||
|
||||
// We are using user-defined, custom rollover settings.
|
||||
if (updatedPolicy.phases.hot!.actions.rollover?.max_age) {
|
||||
hotPhaseActions.rollover.max_age = `${hotPhaseActions.rollover.max_age}${_meta.hot.customRollover.maxAgeUnit}`;
|
||||
hotPhaseActions.rollover.max_age = `${hotPhaseActions.rollover.max_age}${_meta.hot?.customRollover.maxAgeUnit}`;
|
||||
} else {
|
||||
delete hotPhaseActions.rollover.max_age;
|
||||
}
|
||||
|
@ -73,7 +71,7 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => (
|
|||
}
|
||||
|
||||
if (updatedPolicy.phases.hot!.actions.rollover?.max_size) {
|
||||
hotPhaseActions.rollover.max_size = `${hotPhaseActions.rollover.max_size}${_meta.hot.customRollover.maxStorageSizeUnit}`;
|
||||
hotPhaseActions.rollover.max_size = `${hotPhaseActions.rollover.max_size}${_meta.hot?.customRollover.maxStorageSizeUnit}`;
|
||||
} else {
|
||||
delete hotPhaseActions.rollover.max_size;
|
||||
}
|
||||
|
@ -84,20 +82,20 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => (
|
|||
*/
|
||||
if (!updatedPolicy.phases.hot!.actions?.forcemerge) {
|
||||
delete hotPhaseActions.forcemerge;
|
||||
} else if (_meta.hot.bestCompression) {
|
||||
} else if (_meta.hot?.bestCompression) {
|
||||
hotPhaseActions.forcemerge!.index_codec = 'best_compression';
|
||||
} else {
|
||||
delete hotPhaseActions.forcemerge!.index_codec;
|
||||
}
|
||||
|
||||
if (_meta.hot.bestCompression && hotPhaseActions.forcemerge) {
|
||||
if (_meta.hot?.bestCompression && hotPhaseActions.forcemerge) {
|
||||
hotPhaseActions.forcemerge.index_codec = 'best_compression';
|
||||
}
|
||||
|
||||
/**
|
||||
* HOT PHASE READ-ONLY
|
||||
*/
|
||||
if (_meta.hot.readonlyEnabled) {
|
||||
if (_meta.hot?.readonlyEnabled) {
|
||||
hotPhaseActions.readonly = hotPhaseActions.readonly ?? {};
|
||||
} else {
|
||||
delete hotPhaseActions.readonly;
|
||||
|
@ -140,17 +138,9 @@ export const createSerializer = (originalPolicy?: SerializedPolicy) => (
|
|||
/**
|
||||
* WARM PHASE MIN AGE
|
||||
*
|
||||
* If warm phase on rollover is enabled, delete min age field
|
||||
* An index lifecycle switches to warm phase when rollover occurs, so you cannot specify a warm phase time
|
||||
* They are mutually exclusive
|
||||
*/
|
||||
if (
|
||||
(!isUsingRollover || !_meta.warm.warmPhaseOnRollover) &&
|
||||
updatedPolicy.phases.warm?.min_age
|
||||
) {
|
||||
if (updatedPolicy.phases.warm?.min_age) {
|
||||
warmPhase.min_age = `${updatedPolicy.phases.warm!.min_age}${_meta.warm.minAgeUnit}`;
|
||||
} else {
|
||||
delete warmPhase.min_age;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,10 +40,10 @@ export const i18nTexts = {
|
|||
defaultMessage: 'Number of segments',
|
||||
}
|
||||
),
|
||||
setPriorityFieldLabel: i18n.translate(
|
||||
indexPriorityFieldLabel: i18n.translate(
|
||||
'xpack.indexLifecycleMgmt.editPolicy.indexPriorityLabel',
|
||||
{
|
||||
defaultMessage: 'Index priority (optional)',
|
||||
defaultMessage: 'Index priority',
|
||||
}
|
||||
),
|
||||
bestCompressionFieldLabel: i18n.translate(
|
||||
|
@ -170,5 +170,30 @@ export const i18nTexts = {
|
|||
}
|
||||
),
|
||||
},
|
||||
titles: {
|
||||
hot: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseTitle', {
|
||||
defaultMessage: 'Hot phase',
|
||||
}),
|
||||
warm: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseTitle', {
|
||||
defaultMessage: 'Warm phase',
|
||||
}),
|
||||
cold: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseTitle', {
|
||||
defaultMessage: 'Cold phase',
|
||||
}),
|
||||
},
|
||||
descriptions: {
|
||||
hot: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseDescription', {
|
||||
defaultMessage:
|
||||
'This phase is required. You are actively querying and writing to your index. For faster updates, you can roll over the index when it gets too big or too old.',
|
||||
}),
|
||||
warm: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseDescription', {
|
||||
defaultMessage:
|
||||
'You are still querying your index, but it is read-only. You can allocate shards to less performant hardware. For faster searches, you can reduce the number of shards and force merge segments.',
|
||||
}),
|
||||
cold: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseDescription', {
|
||||
defaultMessage:
|
||||
'You are querying your index less frequently, so you can allocate shards on significantly less performant hardware. Because your queries are slower, you can reduce the number of replicas.',
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -70,9 +70,10 @@ export interface PhaseAgeInMilliseconds {
|
|||
const phaseOrder: Phase[] = ['hot', 'warm', 'cold', 'delete'];
|
||||
|
||||
const getMinAge = (phase: MinAgePhase, formData: FormInternal) => ({
|
||||
min_age: formData.phases[phase]?.min_age
|
||||
? formData.phases[phase]!.min_age! + formData._meta[phase].minAgeUnit
|
||||
: '0ms',
|
||||
min_age:
|
||||
formData.phases && formData.phases[phase]?.min_age
|
||||
? formData.phases[phase]!.min_age! + formData._meta[phase].minAgeUnit
|
||||
: '0ms',
|
||||
});
|
||||
|
||||
const formDataToAbsoluteTimings = (formData: FormInternal): AbsoluteTimings => {
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
UIM_CONFIG_WARM_PHASE,
|
||||
UIM_CONFIG_SET_PRIORITY,
|
||||
UIM_CONFIG_FREEZE_INDEX,
|
||||
defaultPhaseIndexPriority,
|
||||
defaultIndexPriority,
|
||||
} from '../constants/';
|
||||
|
||||
import { getUiMetricsForPhases } from './ui_metric';
|
||||
|
@ -22,7 +22,7 @@ describe('getUiMetricsForPhases', () => {
|
|||
min_age: '0ms',
|
||||
actions: {
|
||||
set_priority: {
|
||||
priority: parseInt(defaultPhaseIndexPriority, 10),
|
||||
priority: parseInt(defaultIndexPriority.cold, 10),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -37,7 +37,7 @@ describe('getUiMetricsForPhases', () => {
|
|||
min_age: '0ms',
|
||||
actions: {
|
||||
set_priority: {
|
||||
priority: parseInt(defaultPhaseIndexPriority, 10),
|
||||
priority: parseInt(defaultIndexPriority.warm, 10),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -52,7 +52,7 @@ describe('getUiMetricsForPhases', () => {
|
|||
min_age: '0ms',
|
||||
actions: {
|
||||
set_priority: {
|
||||
priority: parseInt(defaultPhaseIndexPriority, 10) + 1,
|
||||
priority: parseInt(defaultIndexPriority.warm, 10) + 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -68,7 +68,7 @@ describe('getUiMetricsForPhases', () => {
|
|||
actions: {
|
||||
freeze: {},
|
||||
set_priority: {
|
||||
priority: parseInt(defaultPhaseIndexPriority, 10),
|
||||
priority: parseInt(defaultIndexPriority.cold, 10),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -19,8 +19,7 @@ import {
|
|||
UIM_CONFIG_FREEZE_INDEX,
|
||||
UIM_CONFIG_SET_PRIORITY,
|
||||
UIM_CONFIG_WARM_PHASE,
|
||||
defaultSetPriority,
|
||||
defaultPhaseIndexPriority,
|
||||
defaultIndexPriority,
|
||||
} from '../constants';
|
||||
|
||||
import { Phases } from '../../../common/types';
|
||||
|
@ -50,17 +49,17 @@ export function getUiMetricsForPhases(phases: Phases): string[] {
|
|||
const isHotPhasePriorityChanged =
|
||||
phases.hot &&
|
||||
phases.hot.actions.set_priority &&
|
||||
phases.hot.actions.set_priority.priority !== parseInt(defaultSetPriority, 10);
|
||||
phases.hot.actions.set_priority.priority !== parseInt(defaultIndexPriority.hot, 10);
|
||||
|
||||
const isWarmPhasePriorityChanged =
|
||||
phases.warm &&
|
||||
phases.warm.actions.set_priority &&
|
||||
phases.warm.actions.set_priority.priority !== parseInt(defaultPhaseIndexPriority, 10);
|
||||
phases.warm.actions.set_priority.priority !== parseInt(defaultIndexPriority.warm, 10);
|
||||
|
||||
const isColdPhasePriorityChanged =
|
||||
phases.cold &&
|
||||
phases.cold.actions.set_priority &&
|
||||
phases.cold.actions.set_priority.priority !== parseInt(defaultPhaseIndexPriority, 10);
|
||||
phases.cold.actions.set_priority.priority !== parseInt(defaultIndexPriority.cold, 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 (
|
||||
|
|
|
@ -31,6 +31,7 @@ export {
|
|||
SuperSelectField,
|
||||
ComboBoxField,
|
||||
TextField,
|
||||
CheckBoxField,
|
||||
} from '../../../../src/plugins/es_ui_shared/static/forms/components';
|
||||
|
||||
export { attemptToURIDecode } from '../../../../src/plugins/es_ui_shared/public';
|
||||
|
|
|
@ -9416,9 +9416,7 @@
|
|||
"xpack.indexLifecycleMgmt.coldPhase.dataTier.defaultAllocationNotAvailableTitle": "コールドティアに割り当てられているノードがありません",
|
||||
"xpack.indexLifecycleMgmt.coldPhase.dataTier.description": "頻度が低い読み取り専用アクセス用に最適化されたノードにデータを移動します。安価なハードウェアのコールドフェーズにデータを格納します。",
|
||||
"xpack.indexLifecycleMgmt.coldPhase.freezeIndexLabel": "インデックスを凍結",
|
||||
"xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasDescription": "レプリカの数を設定します。デフォルトでは前のフェーズと同じです。",
|
||||
"xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasLabel": "レプリカ数(任意)",
|
||||
"xpack.indexLifecycleMgmt.coldPhase.replicasTitle": "レプリカ",
|
||||
"xpack.indexLifecycleMgmt.common.dataTier.title": "データ割り当て",
|
||||
"xpack.indexLifecycleMgmt.confirmDelete.cancelButton": "キャンセル",
|
||||
"xpack.indexLifecycleMgmt.confirmDelete.deleteButton": "削除",
|
||||
|
@ -9431,11 +9429,8 @@
|
|||
"xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.title": "コールドティアを作成",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.cold.nodeAttributesMissingDescription": "属性に基づく割り当てを使用するには、elasticsearch.yml でカスタムノード属性を定義します。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.coldPhase.activateColdPhaseSwitchLabel": "コールドフェーズを有効にする",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseDescriptionText": "インデックスへのクエリの頻度を減らすことで、大幅に性能が低いハードウェアにシャードを割り当てることができます。クエリが遅いため、複製の数を減らすことができます。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseLabel": "コールドフェーズ",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeIndexExplanationText": "インデックスを読み取り専用にし、メモリー消費量を最小化します。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeText": "凍結",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel": "レプリカを設定",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.helpText": "ノード属性に基づいてデータを移動します。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.input": "カスタム",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.helpText": "コールドティアのノードにデータを移動します。",
|
||||
|
@ -9452,13 +9447,6 @@
|
|||
"xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage": "インデックスライフサイクルポリシーを作成します",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.createSearchableSnapshotLink": "スナップショットリポジドリを作成",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.createSnapshotRepositoryLink": "新しいスナップショットリポジドリを作成",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationDaysOptionLabel": "インデックスの作成からの経過日数",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationHoursOptionLabel": "インデックスの作成からの経過時間数",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationMicroSecondsOptionLabel": "インデックスの作成からの経過時間(マイクロ秒)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationMilliSecondsOptionLabel": "インデックスの作成からの経過時間(ミリ秒)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationMinutesOptionLabel": "インデックスの作成からの経過時間(分)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationNanoSecondsOptionLabel": "インデックスの作成からの経過時間(ナノ秒)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationSecondsOptionLabel": "インデックスの作成からの経過時間(秒)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.dataTierAllocation.allocationFieldLabel": "データティアオプション",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.dataTierAllocation.nodeAllocationFieldLabel": "ノード属性を選択",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.dataTierColdLabel": "コールド",
|
||||
|
@ -9499,23 +9487,17 @@
|
|||
"xpack.indexLifecycleMgmt.editPolicy.formErrorsMessage": "このページのエラーを修正してください。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hidePolicyJsonButto": "リクエストを非表示",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hotPhase.enableRolloverTipContent": "現在のインデックスが定義された条件のいずれかを満たすときに、新しいインデックスにロールオーバーします。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseDescriptionMessage": "このフェーズは必須です。アクティブにクエリを実行しインデックスに書き込んでいます。 更新を高速化するため、大きくなりすぎたり古くなりすぎたりした際にインデックスをロールオーバーできます。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseLabel": "ホットフェーズ",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hotPhase.learnAboutRolloverLinkText": "詳細",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hotPhase.rolloverDefaultsTipContent": "インデックスが 30 日経過するか、50 GB に達したらロールオーバーします。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hotPhase.rolloverDescriptionMessage": "効率的なストレージと高いパフォーマンスのための時系列データの自動ロールアウト。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.indexPriorityLabel": "インデックス優先度(任意)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.indexPriorityText": "インデックスの優先順位",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.learnAboutIndexLifecycleManagementLinkText": "インデックスライフサイクルの詳細をご覧ください。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.learnAboutIndexTemplatesLink": "インデックステンプレートの詳細をご覧ください",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.learnAboutShardAllocationLink": "シャード割り当ての詳細をご覧ください",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.learnAboutTimingText": "タイミングの詳細をご覧ください",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.lifecyclePoliciesLoadingFailedTitle": "既存のライフサイクルポリシーを読み込めません",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.lifecyclePoliciesReloadButton": "再試行",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.lifecyclePolicyDescriptionText": "インデックスへのアクティブな書き込みから削除までの、インデックスライフサイクルの 4 つのフェーズを自動化するには、インデックスポリシーを使用します。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.loadSnapshotRepositoriesErrorBody": "このフィールドを更新し、既存のスナップショットリポジトリの名前を入力します。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.loadSnapshotRepositoriesErrorTitle": "スナップショットリポジトリを読み込めません",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.nameLabel": "名前",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.customOption.description": "ノード属性を使用して、シャード割り当てを制御します。{learnMoreLink}。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption": "割り当て構成を修正しない",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.nodeAttributesLoadingFailedTitle": "ノードデータを読み込めません",
|
||||
|
@ -9542,13 +9524,6 @@
|
|||
"xpack.indexLifecycleMgmt.editPolicy.readonlyDescription": "有効にすると、インデックスおよびインデックスメタデータを読み取り専用にします。無効にすると、書き込みとメタデータの変更を許可します。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.readonlyTitle": "読み取り専用",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.reloadSnapshotRepositoriesLabel": "スナップショットリポジドリの再読み込み",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverDaysOptionLabel": "ロールオーバーからの経過日数",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverHoursOptionLabel": "ロールオーバーからの経過時間数",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverMicroSecondsOptionLabel": "ロールオーバーからの経過時間(マイクロ秒)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverMilliSecondsOptionLabel": "ロールオーバーからの経過時間(ミリ秒)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverMinutesOptionLabel": "ロールオーバーからの経過時間数(分)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverNanoSecondsOptionLabel": "ロールオーバーからの経過時間(ナノ秒)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverSecondsOptionLabel": "ロールオーバーからの経過時間(秒)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.saveAsNewButton": "新規ポリシーとして保存します",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.saveAsNewPolicyMessage": "新規ポリシーとして保存します",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.saveButton": "ポリシーを保存",
|
||||
|
@ -9573,15 +9548,11 @@
|
|||
"xpack.indexLifecycleMgmt.editPolicy.warm.nodeAttributesMissingDescription": "属性に基づく割り当てを使用するには、elasticsearch.yml でカスタムノード属性を定義します。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.warmPhase.activateWarmPhaseSwitchLabel": "ウォームフェーズを有効にする",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.warmPhase.indexPriorityExplanationText": "ノードの再起動後にインデックスを復元する優先順位を設定します。優先順位の高いインデックスは優先順位の低いインデックスよりも先に復元されます。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.warmPhase.numberOfReplicas.switchLabel": "レプリカを設定",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseDescriptionMessage": "まだインデックスにクエリを実行中ですが、読み取り専用です。性能の低いハードウェアにシャードを割り当てることができます。検索を高速化するために、シャードの数を減らしセグメントを結合することができます。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseLabel": "ウォームフェーズ",
|
||||
"xpack.indexLifecycleMgmt.featureCatalogueDescription": "ライフサイクルポリシーを定義し、インデックス年齢として自動的に処理を実行します。",
|
||||
"xpack.indexLifecycleMgmt.featureCatalogueTitle": "インデックスライフサイクルを管理",
|
||||
"xpack.indexLifecycleMgmt.forcemerge.bestCompressionLabel": "格納されたフィールドを圧縮",
|
||||
"xpack.indexLifecycleMgmt.forcemerge.enableLabel": "データを強制結合",
|
||||
"xpack.indexLifecycleMgmt.forceMerge.numberOfSegmentsLabel": "セグメントの数",
|
||||
"xpack.indexLifecycleMgmt.hotPhase.advancedSettingsButton": "高度な設定",
|
||||
"xpack.indexLifecycleMgmt.hotPhase.bytesLabel": "バイト",
|
||||
"xpack.indexLifecycleMgmt.hotPhase.daysLabel": "日",
|
||||
"xpack.indexLifecycleMgmt.hotPhase.enableRolloverLabel": "ロールオーバーを有効にする",
|
||||
|
@ -9705,7 +9676,6 @@
|
|||
"xpack.indexLifecycleMgmt.shrink.indexFieldLabel": "インデックスを縮小",
|
||||
"xpack.indexLifecycleMgmt.shrink.numberOfPrimaryShardsLabel": "プライマリシャードの数",
|
||||
"xpack.indexLifecycleMgmt.templateNotFoundMessage": "テンプレート{name}が見つかりません。",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.advancedSettingsButton": "高度な設定",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableBody": "ロールに基づく割り当てを使用するには、1つ以上のノードを、ウォームまたはホットティアに割り当てます。使用可能なノードがない場合、ポリシーは割り当てを完了できません。",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableTitle": "ウォームティアに割り当てられているノードがありません",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold": "このポリシーはコールドフェーズのデータを{tier}ティアノードに移動します。",
|
||||
|
@ -9713,10 +9683,7 @@
|
|||
"xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm": "このポリシーはウォームフェーズのデータを{tier}ティアノードに移動します。",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm.title": "ウォームティアに割り当てられているノードがありません",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.dataTier.description": "頻度が低い読み取り専用アクセス用に最適化されたノードにデータを移動します。",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.moveToWarmPhaseOnRolloverLabel": "ロールオーバー時にウォームフェーズに変更",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasDescription": "レプリカの数を設定します。デフォルトでは前のフェーズと同じです。",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasLabel": "レプリカ数(任意)",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.replicasTitle": "レプリカ",
|
||||
"xpack.infra.alerting.alertFlyout.groupBy.placeholder": "なし(グループなし)",
|
||||
"xpack.infra.alerting.alertFlyout.groupByLabel": "グループ分けの条件",
|
||||
"xpack.infra.alerting.alertsButton": "アラート",
|
||||
|
|
|
@ -9440,9 +9440,7 @@
|
|||
"xpack.indexLifecycleMgmt.coldPhase.dataTier.defaultAllocationNotAvailableTitle": "没有分配到冷层的节点",
|
||||
"xpack.indexLifecycleMgmt.coldPhase.dataTier.description": "将数据移到针对不太频繁的只读访问优化的节点。将处于冷阶段的数据存储在成本较低的硬件上。",
|
||||
"xpack.indexLifecycleMgmt.coldPhase.freezeIndexLabel": "冻结索引",
|
||||
"xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasDescription": "设置副本数目。默认情况下仍与上一阶段相同。",
|
||||
"xpack.indexLifecycleMgmt.coldPhase.numberOfReplicasLabel": "副本分片数(可选)",
|
||||
"xpack.indexLifecycleMgmt.coldPhase.replicasTitle": "副本分片",
|
||||
"xpack.indexLifecycleMgmt.common.dataTier.title": "数据分配",
|
||||
"xpack.indexLifecycleMgmt.confirmDelete.cancelButton": "取消",
|
||||
"xpack.indexLifecycleMgmt.confirmDelete.deleteButton": "删除",
|
||||
|
@ -9455,11 +9453,8 @@
|
|||
"xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.title": "创建冷层",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.cold.nodeAttributesMissingDescription": "在 elasticsearch.yml 中定义定制节点属性,以使用基于属性的分配。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.coldPhase.activateColdPhaseSwitchLabel": "激活冷阶段",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseDescriptionText": "您查询自己索引的频率较低,因此您可以在效率较低的硬件上分配分片。因为您的查询较为缓慢,所以您可以减少副本分片数目。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.coldPhase.coldPhaseLabel": "冷阶段",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeIndexExplanationText": "使索引只读,并最大限度减小其内存占用。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.coldPhase.freezeText": "冻结",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.coldPhase.numberOfReplicas.switchLabel": "设置副本",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.helpText": "根据节点属性移动数据。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.customOption.input": "定制",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.common.dataTierAllocation.cold.defaultOption.helpText": "将数据移到冷层中的节点。",
|
||||
|
@ -9476,13 +9471,6 @@
|
|||
"xpack.indexLifecycleMgmt.editPolicy.createPolicyMessage": "创建索引生命周期策略",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.createSearchableSnapshotLink": "创建快照库",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.createSnapshotRepositoryLink": "创建新的快照库",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationDaysOptionLabel": "天(自索引创建)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationHoursOptionLabel": "小时(自索引创建)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationMicroSecondsOptionLabel": "微秒(自索引创建)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationMilliSecondsOptionLabel": "毫秒(自索引创建)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationMinutesOptionLabel": "分钟(自索引创建)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationNanoSecondsOptionLabel": "纳秒(自索引创建)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.creationSecondsOptionLabel": "秒(自索引创建)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.dataTierAllocation.allocationFieldLabel": "数据层选项",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.dataTierAllocation.nodeAllocationFieldLabel": "选择节点属性",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.dataTierColdLabel": "冷",
|
||||
|
@ -9523,23 +9511,17 @@
|
|||
"xpack.indexLifecycleMgmt.editPolicy.formErrorsMessage": "请修复此页面上的错误。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hidePolicyJsonButto": "隐藏请求",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hotPhase.enableRolloverTipContent": "在当前索引满足定义的条件之一时,滚动更新到新索引。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseDescriptionMessage": "此阶段为必需。您正频繁地查询并写到您的索引。 为了获取更快的更新,在索引变得过大或过旧时,您可以滚动更新索引。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hotPhase.hotPhaseLabel": "热阶段",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hotPhase.learnAboutRolloverLinkText": "了解详情",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hotPhase.rolloverDefaultsTipContent": "当索引已存在 30 天或达到 50 GB 时滚动更新。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.hotPhase.rolloverDescriptionMessage": "自动滚动更新时间序列数据,以实现高效存储和更高性能。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.indexPriorityLabel": "索引优先级(可选)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.indexPriorityText": "索引优先级",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.learnAboutIndexLifecycleManagementLinkText": "了解索引生命周期。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.learnAboutIndexTemplatesLink": "了解索引模板",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.learnAboutShardAllocationLink": "了解分片分配",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.learnAboutTimingText": "了解计时",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.lifecyclePoliciesLoadingFailedTitle": "无法加载现有生命周期策略",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.lifecyclePoliciesReloadButton": "重试",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.lifecyclePolicyDescriptionText": "使用索引策略自动化索引生命周期的四个阶段,从频繁地写入到索引到删除索引。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.loadSnapshotRepositoriesErrorBody": "刷新此字段并输入现有快照储存库的名称。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.loadSnapshotRepositoriesErrorTitle": "无法加载快照存储库",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.nameLabel": "名称",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.customOption.description": "使用节点属性控制分片分配。{learnMoreLink}。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.nodeAllocation.doNotModifyAllocationOption": "切勿修改分配配置",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.nodeAttributesLoadingFailedTitle": "无法加载节点数据",
|
||||
|
@ -9566,13 +9548,6 @@
|
|||
"xpack.indexLifecycleMgmt.editPolicy.readonlyDescription": "启用以使索引及索引元数据只读;禁用以允许写入和元数据更改。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.readonlyTitle": "只读",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.reloadSnapshotRepositoriesLabel": "重新加载快照存储库",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverDaysOptionLabel": "天(自滚动更新)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverHoursOptionLabel": "小时(自滚动更新)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverMicroSecondsOptionLabel": "微秒(自滚动更新)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverMilliSecondsOptionLabel": "毫秒(自滚动更新)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverMinutesOptionLabel": "分钟(自滚动更新)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverNanoSecondsOptionLabel": "纳秒(自滚动更新)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.rolloverSecondsOptionLabel": "秒(自滚动更新)",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.saveAsNewButton": "另存为新策略",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.saveAsNewPolicyMessage": "另存为新策略",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.saveButton": "保存策略",
|
||||
|
@ -9597,15 +9572,11 @@
|
|||
"xpack.indexLifecycleMgmt.editPolicy.warm.nodeAttributesMissingDescription": "在 elasticsearch.yml 中定义定制节点属性,以使用基于属性的分配。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.warmPhase.activateWarmPhaseSwitchLabel": "激活温阶段",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.warmPhase.indexPriorityExplanationText": "设置在节点重新启动后恢复索引的优先级。较高优先级的索引会在较低优先级的索引之前恢复。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.warmPhase.numberOfReplicas.switchLabel": "设置副本",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseDescriptionMessage": "您仍在查询自己的索引,但其为只读。您可以将分片分配给效率较低的硬件。为了获取更快的搜索,您可以减少分片数目并强制合并段。",
|
||||
"xpack.indexLifecycleMgmt.editPolicy.warmPhase.warmPhaseLabel": "温阶段",
|
||||
"xpack.indexLifecycleMgmt.featureCatalogueDescription": "定义生命周期策略,以随着索引老化自动执行操作。",
|
||||
"xpack.indexLifecycleMgmt.featureCatalogueTitle": "管理索引生命周期",
|
||||
"xpack.indexLifecycleMgmt.forcemerge.bestCompressionLabel": "压缩已存储字段",
|
||||
"xpack.indexLifecycleMgmt.forcemerge.enableLabel": "强制合并数据",
|
||||
"xpack.indexLifecycleMgmt.forceMerge.numberOfSegmentsLabel": "分段数目",
|
||||
"xpack.indexLifecycleMgmt.hotPhase.advancedSettingsButton": "高级设置",
|
||||
"xpack.indexLifecycleMgmt.hotPhase.bytesLabel": "字节",
|
||||
"xpack.indexLifecycleMgmt.hotPhase.daysLabel": "天",
|
||||
"xpack.indexLifecycleMgmt.hotPhase.enableRolloverLabel": "启用滚动更新",
|
||||
|
@ -9731,7 +9702,6 @@
|
|||
"xpack.indexLifecycleMgmt.shrink.indexFieldLabel": "缩小索引",
|
||||
"xpack.indexLifecycleMgmt.shrink.numberOfPrimaryShardsLabel": "主分片数目",
|
||||
"xpack.indexLifecycleMgmt.templateNotFoundMessage": "找不到模板 {name}。",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.advancedSettingsButton": "高级设置",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableBody": "至少将一个节点分配到温层或冷层,以使用基于角色的分配。如果没有可用节点,则策略无法完成分配。",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableTitle": "没有分配到温层的节点",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold": "此策略会改为将冷阶段的数据移到{tier}层节点。",
|
||||
|
@ -9739,10 +9709,7 @@
|
|||
"xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm": "此策略会改为将温阶段的数据移到{tier}层节点。",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm.title": "没有分配到温层的节点",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.dataTier.description": "将数据移到针对不太频繁的只读访问优化的节点。",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.moveToWarmPhaseOnRolloverLabel": "滚动更新时移到温阶段",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasDescription": "设置副本数目。默认情况下仍与上一阶段相同。",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.numberOfReplicasLabel": "副本分片数(可选)",
|
||||
"xpack.indexLifecycleMgmt.warmPhase.replicasTitle": "副本分片",
|
||||
"xpack.infra.alerting.alertFlyout.groupBy.placeholder": "无内容(未分组)",
|
||||
"xpack.infra.alerting.alertFlyout.groupByLabel": "分组依据",
|
||||
"xpack.infra.alerting.alertsButton": "告警",
|
||||
|
|
Loading…
Reference in a new issue