Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide guidance of "Custom" allocation behavior in ILM #96111

Merged
merged 19 commits into from
May 1, 2021
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
4c1f6a7
Refine ILM allocation UX.
cjcenizal Apr 1, 2021
fe5850b
Localize disableDataTierOption flag instead of passing it as a prop, …
cjcenizal Apr 1, 2021
0ebf824
Clarify the scenario in which the user has selected node_attrs alloca…
cjcenizal Apr 5, 2021
f257625
Merge branch 'master' into bug/duplicate-allocation-ux
cjcenizal Apr 24, 2021
67474bc
Remove inapplicable frozen tier from NoTiersAvailableNotice.
cjcenizal Apr 24, 2021
1f4ffb2
Adjust copy for clarity: data remains on fallback nodes and subtly ur…
cjcenizal Apr 24, 2021
8361de4
Split up node allocation tests to improve discoverability. Refactor t…
cjcenizal Apr 25, 2021
b9a9cff
Merge branch 'master' into bug/duplicate-allocation-ux
kibanamachine Apr 25, 2021
8f17c47
Merge branch 'master' into bug/duplicate-allocation-ux
cjcenizal Apr 27, 2021
4e06e3b
Consume init_test_bed in edit_policy.helpers.
cjcenizal Apr 27, 2021
3bae91c
Create helpers/types file to store extracted Phase type.
cjcenizal Apr 27, 2021
2482fa7
Merge branch 'master' into bug/duplicate-allocation-ux
cjcenizal Apr 28, 2021
d3f480f
Apply JL's feedback: rename tsx->ts filetypes, fix typo, remove unuse…
cjcenizal Apr 28, 2021
c1b1c1e
Merge branch 'master' into bug/duplicate-allocation-ux
cjcenizal Apr 29, 2021
d0e21f0
Adjust copy to consistently notify the user that node attributes are …
cjcenizal Apr 30, 2021
923a6c2
Remove redundant beforeEach from general_behavior tests.
cjcenizal Apr 30, 2021
fd44a88
Update tests.
cjcenizal Apr 30, 2021
0e7b903
Merge branch 'master' into bug/duplicate-allocation-ux
cjcenizal Apr 30, 2021
ffa283e
Final copy polish.
cjcenizal May 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_reac
import { createBreadcrumbsMock } from '../../../public/application/services/breadcrumbs.mock';
import { licensingMock } from '../../../../licensing/public/mocks';
import { App } from '../../../public/application/app';
import { TestSubjects } from '../helpers';

const breadcrumbService = createBreadcrumbsMock();

Expand All @@ -37,7 +36,7 @@ const getTestBedConfig = (initialEntries: string[]): TestBedConfig => ({
const initTestBed = (initialEntries: string[]) =>
registerTestBed(AppWithContext, getTestBedConfig(initialEntries))();

export interface AppTestBed extends TestBed<TestSubjects> {
export interface AppTestBed extends TestBed {
actions: {
clickPolicyNameLink: () => void;
clickCreatePolicyButton: () => void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,88 +5,23 @@
* 2.0.
*/

import React from 'react';
import { act } from 'react-dom/test-utils';
import { TestBedConfig } from '@kbn/test/jest';

import { registerTestBed, TestBedConfig } from '@kbn/test/jest';

import { licensingMock } from '../../../../licensing/public/mocks';

import { EditPolicy } from '../../../public/application/sections/edit_policy';
import { DataTierAllocationType } from '../../../public/application/sections/edit_policy/types';

import { Phases as PolicyPhases } from '../../../common/types';

import { KibanaContextProvider } from '../../../public/shared_imports';
import { AppServicesContext } from '../../../public/types';
import { createBreadcrumbsMock } from '../../../public/application/services/breadcrumbs.mock';

import { TestSubjects } from '../helpers';
import { POLICY_NAME } from './constants';

type Phases = keyof PolicyPhases;

window.scrollTo = jest.fn();

jest.mock('@elastic/eui', () => {
const original = jest.requireActual('@elastic/eui');

return {
...original,
// Mocking EuiComboBox, as it utilizes "react-virtualized" for rendering search suggestions,
// which does not produce a valid component wrapper
EuiComboBox: (props: any) => (
<input
data-test-subj={props['data-test-subj'] || 'mockComboBox'}
data-currentvalue={props.selectedOptions}
onChange={async (syntheticEvent: any) => {
props.onChange([syntheticEvent['0']]);
}}
/>
),
EuiIcon: 'eui-icon', // using custom react-svg icon causes issues, mocking for now.
};
});

const getTestBedConfig = (testBedConfigArgs?: Partial<TestBedConfig>): TestBedConfig => {
return {
memoryRouter: {
initialEntries: [`/policies/edit/${POLICY_NAME}`],
componentRoutePath: `/policies/edit/:policyName`,
},
defaultProps: {
getUrlForApp: () => {},
},
...testBedConfigArgs,
};
};

const breadcrumbService = createBreadcrumbsMock();

const MyComponent = ({ appServicesContext, ...rest }: any) => {
return (
<KibanaContextProvider
services={{
breadcrumbService,
license: licensingMock.createLicense({ license: { type: 'enterprise' } }),
...appServicesContext,
}}
>
<EditPolicy {...rest} />
</KibanaContextProvider>
);
};

const initTestBed = (arg?: {
appServicesContext?: Partial<AppServicesContext>;
testBedConfig?: Partial<TestBedConfig>;
}) => {
const { testBedConfig: testBedConfigArgs, ...rest } = arg || {};
return registerTestBed<TestSubjects>(MyComponent, getTestBedConfig(testBedConfigArgs))(rest);
};
import {
Phase,
createEnablePhaseAction,
createNodeAllocationActions,
createFormToggleAction,
createFormSetValueAction,
setReplicas,
savePolicy,
} from '../helpers';
import { initTestBed } from './init_test_bed';

type SetupReturn = ReturnType<typeof setup>;

export type EditPolicyTestBed = SetupReturn extends Promise<infer U> ? U : SetupReturn;

export const setup = async (arg?: {
Expand All @@ -97,46 +32,23 @@ export const setup = async (arg?: {

const { find, component, form, exists } = testBed;

const createFormToggleAction = (dataTestSubject: string) => async (checked: boolean) => {
await act(async () => {
form.toggleEuiSwitch(dataTestSubject, checked);
});
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 () => {
form.setInputValue(dataTestSubject, value);
});
component.update();
};
}

const setWaitForSnapshotPolicy = async (snapshotPolicyName: string) => {
act(() => {
find('snapshotPolicyCombobox').simulate('change', [{ label: snapshotPolicyName }]);
});
component.update();
};

const savePolicy = async () => {
await act(async () => {
find('savePolicyButton').simulate('click');
});
component.update();
};

const toggleDefaultRollover = createFormToggleAction('useDefaultRolloverSwitch');
const toggleDefaultRollover = createFormToggleAction(testBed, 'useDefaultRolloverSwitch');

const toggleRollover = createFormToggleAction('rolloverSwitch');
const toggleRollover = createFormToggleAction(testBed, 'rolloverSwitch');

const setMaxPrimaryShardSize = async (value: string, units?: string) => {
await act(async () => {
Expand All @@ -162,7 +74,7 @@ export const setup = async (arg?: {
component.update();
};

const setMaxDocs = createFormSetValueAction('hot-selectedMaxDocuments');
const setMaxDocs = createFormSetValueAction(testBed, 'hot-selectedMaxDocuments');

const setMaxAge = async (value: string, units?: string) => {
await act(async () => {
Expand All @@ -174,69 +86,64 @@ export const setup = async (arg?: {
component.update();
};

const createForceMergeActions = (phase: Phases) => {
const createForceMergeActions = (phase: Phase) => {
const toggleSelector = `${phase}-forceMergeSwitch`;
return {
forceMergeFieldExists: () => exists(toggleSelector),
toggleForceMerge: createFormToggleAction(toggleSelector),
setForcemergeSegmentsCount: createFormSetValueAction(`${phase}-selectedForceMergeSegments`),
toggleForceMerge: createFormToggleAction(testBed, toggleSelector),
setForcemergeSegmentsCount: createFormSetValueAction(
testBed,
`${phase}-selectedForceMergeSegments`
),
setBestCompression: createFormCheckboxAction(`${phase}-bestCompression`),
};
};

const createIndexPriorityActions = (phase: Phases) => {
const createIndexPriorityActions = (phase: Phase) => {
const toggleSelector = `${phase}-indexPrioritySwitch`;
return {
indexPriorityExists: () => exists(toggleSelector),
toggleIndexPriority: createFormToggleAction(toggleSelector),
setIndexPriority: createFormSetValueAction(`${phase}-indexPriority`),
toggleIndexPriority: createFormToggleAction(testBed, toggleSelector),
setIndexPriority: createFormSetValueAction(testBed, `${phase}-indexPriority`),
};
};

const enable = (phase: Phases) => createFormToggleAction(`enablePhaseSwitch-${phase}`);

const createMinAgeActions = (phase: Phases) => {
const createMinAgeActions = (phase: Phase) => {
return {
hasMinAgeInput: () => exists(`${phase}-selectedMinimumAge`),
setMinAgeValue: createFormSetValueAction(`${phase}-selectedMinimumAge`),
setMinAgeUnits: createFormSetValueAction(`${phase}-selectedMinimumAgeUnits`),
setMinAgeValue: createFormSetValueAction(testBed, `${phase}-selectedMinimumAge`),
setMinAgeUnits: createFormSetValueAction(testBed, `${phase}-selectedMinimumAgeUnits`),
hasRolloverTipOnMinAge: () => exists(`${phase}-rolloverMinAgeInputIconTip`),
};
};

const setReplicas = (phase: Phases) => async (value: string) => {
if (!exists(`${phase}-selectedReplicaCount`)) {
await createFormToggleAction(`${phase}-setReplicasSwitch`)(true);
}
await createFormSetValueAction(`${phase}-selectedReplicaCount`)(value);
};

const createShrinkActions = (phase: Phases) => {
const createShrinkActions = (phase: Phase) => {
const toggleSelector = `${phase}-shrinkSwitch`;
return {
shrinkExists: () => exists(toggleSelector),
toggleShrink: createFormToggleAction(toggleSelector),
setShrink: createFormSetValueAction(`${phase}-primaryShardCount`),
toggleShrink: createFormToggleAction(testBed, toggleSelector),
setShrink: createFormSetValueAction(testBed, `${phase}-primaryShardCount`),
};
};

const createSetFreeze = (phase: Phases) => createFormToggleAction(`${phase}-freezeSwitch`);
const createFreezeExists = (phase: Phases) => () => exists(`${phase}-freezeSwitch`);
const createSetFreeze = (phase: Phase) =>
createFormToggleAction(testBed, `${phase}-freezeSwitch`);
const createFreezeExists = (phase: Phase) => () => exists(`${phase}-freezeSwitch`);

const createReadonlyActions = (phase: Phases) => {
const createReadonlyActions = (phase: Phase) => {
const toggleSelector = `${phase}-readonlySwitch`;
return {
readonlyExists: () => exists(toggleSelector),
toggleReadonly: createFormToggleAction(toggleSelector),
toggleReadonly: createFormToggleAction(testBed, toggleSelector),
};
};

const createSearchableSnapshotActions = (phase: Phases) => {
const createSearchableSnapshotActions = (phase: Phase) => {
const fieldSelector = `searchableSnapshotField-${phase}`;
const licenseCalloutSelector = `${fieldSelector}.searchableSnapshotDisabledDueToLicense`;
const toggleSelector = `${fieldSelector}.searchableSnapshotToggle`;

const toggleSearchableSnapshot = createFormToggleAction(toggleSelector);
const toggleSearchableSnapshot = createFormToggleAction(testBed, toggleSelector);
return {
searchableSnapshotDisabled: () =>
exists(licenseCalloutSelector) && find(licenseCalloutSelector).props().disabled === true,
Expand Down Expand Up @@ -269,54 +176,6 @@ export const setup = async (arg?: {

const hasRolloverSettingRequiredCallout = (): boolean => exists('rolloverSettingsRequired');

const createNodeAllocationActions = (phase: Phases) => {
const controlsSelector = `${phase}-dataTierAllocationControls`;
const dataTierSelector = `${controlsSelector}.dataTierSelect`;
const nodeAttrsSelector = `${phase}-selectedNodeAttrs`;

const openNodeAttributesSection = async () => {
await act(async () => {
find(dataTierSelector).simulate('click');
});
component.update();
};

return {
hasDataTierAllocationControls: () => exists(controlsSelector),
openNodeAttributesSection,
hasNodeAttributesSelect: (): boolean => exists(nodeAttrsSelector),
getNodeAttributesSelectOptions: () => find(nodeAttrsSelector).find('option'),
setDataAllocation: async (value: DataTierAllocationType) => {
await openNodeAttributesSection();

await act(async () => {
switch (value) {
case 'node_roles':
find(`${controlsSelector}.defaultDataAllocationOption`).simulate('click');
break;
case 'node_attrs':
find(`${controlsSelector}.customDataAllocationOption`).simulate('click');
break;
default:
find(`${controlsSelector}.noneDataAllocationOption`).simulate('click');
}
});
component.update();
},
setSelectedNodeAttribute: createFormSetValueAction(nodeAttrsSelector),
hasNoNodeAttrsWarning: () => exists('noNodeAttributesWarning'),
hasDefaultAllocationWarning: () => exists('defaultAllocationWarning'),
hasDefaultAllocationNotice: () => exists('defaultAllocationNotice'),
hasNodeDetailsFlyout: () => exists(`${phase}-viewNodeDetailsFlyoutButton`),
openNodeDetailsFlyout: async () => {
await act(async () => {
find(`${phase}-viewNodeDetailsFlyoutButton`).simulate('click');
});
component.update();
},
};
};

const expectErrorMessages = (expectedMessages: string[]) => {
const errorMessages = component.find('.euiFormErrorText');
expect(errorMessages.length).toBe(expectedMessages.length);
Expand Down Expand Up @@ -346,10 +205,10 @@ export const setup = async (arg?: {
...testBed,
runTimers,
actions: {
saveAsNewPolicy: createFormToggleAction('saveAsNewSwitch'),
setPolicyName: createFormSetValueAction('policyNameField'),
saveAsNewPolicy: createFormToggleAction(testBed, 'saveAsNewSwitch'),
setPolicyName: createFormSetValueAction(testBed, 'policyNameField'),
setWaitForSnapshotPolicy,
savePolicy,
savePolicy: () => savePolicy(testBed),
hasGlobalErrorCallout: () => exists('policyFormErrorsCallout'),
expectErrorMessages,
timeline: {
Expand All @@ -375,30 +234,30 @@ export const setup = async (arg?: {
...createSearchableSnapshotActions('hot'),
},
warm: {
enable: enable('warm'),
enable: createEnablePhaseAction(testBed, 'warm'),
...createMinAgeActions('warm'),
setReplicas: setReplicas('warm'),
setReplicas: (value: string) => setReplicas(testBed, 'warm', value),
hasErrorIndicator: () => exists('phaseErrorIndicator-warm'),
...createShrinkActions('warm'),
...createForceMergeActions('warm'),
...createReadonlyActions('warm'),
...createIndexPriorityActions('warm'),
...createNodeAllocationActions('warm'),
...createNodeAllocationActions(testBed, 'warm'),
},
cold: {
enable: enable('cold'),
enable: createEnablePhaseAction(testBed, 'cold'),
...createMinAgeActions('cold'),
setReplicas: setReplicas('cold'),
setReplicas: (value: string) => setReplicas(testBed, 'cold', value),
setFreeze: createSetFreeze('cold'),
freezeExists: createFreezeExists('cold'),
...createReadonlyActions('cold'),
hasErrorIndicator: () => exists('phaseErrorIndicator-cold'),
...createIndexPriorityActions('cold'),
...createSearchableSnapshotActions('cold'),
...createNodeAllocationActions('cold'),
...createNodeAllocationActions(testBed, 'cold'),
},
frozen: {
enable: enable('frozen'),
enable: createEnablePhaseAction(testBed, 'frozen'),
...createMinAgeActions('frozen'),
hasErrorIndicator: () => exists('phaseErrorIndicator-frozen'),
...createSearchableSnapshotActions('frozen'),
Expand Down
Loading