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

[ILM ] Fix logic for showing/hiding recommended allocation on Cloud #90592

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
a197a5a
updated logic for hiding recommended allocation options on cloud and …
jloleysens Feb 8, 2021
40a1858
Merge branch 'master' into ilm/update-condition-for-hiding-recommded-…
kibanamachine Feb 8, 2021
7ed5223
added version check and tests for version check to enable pre v8 beha…
jloleysens Feb 8, 2021
dc70ff9
implement feedback to make tests more legible, fix test names and min…
jloleysens Feb 9, 2021
e11c708
added additional callout for data tier state, also added some new cop…
jloleysens Feb 9, 2021
37ddcfd
remove unused stackVersion context value
jloleysens Feb 9, 2021
39ba98f
Merge branch 'master' into ilm/update-condition-for-hiding-recommded-…
kibanamachine Feb 9, 2021
48099a8
Merge branch 'master' into ilm/update-condition-for-hiding-recommded-…
kibanamachine Feb 9, 2021
b523a5f
Merge branch 'master' into ilm/update-condition-for-hiding-recommded-…
kibanamachine Feb 11, 2021
d9529f5
address windows max path length constraint
jloleysens Feb 11, 2021
6d933b8
Merge branch 'master' into ilm/update-condition-for-hiding-recommded-…
kibanamachine Feb 15, 2021
28ed48d
Merge branch 'master' of github.com:elastic/kibana into ilm/update-co…
jloleysens Feb 15, 2021
9b632d7
Merge branch 'master' into ilm/update-condition-for-hiding-recommded-…
kibanamachine Feb 17, 2021
b4d6ef5
Merge branch 'master' of github.com:elastic/kibana into ilm/update-co…
jloleysens Feb 22, 2021
b6bfe49
- Fix botched conflict resolution!
jloleysens Feb 22, 2021
7746647
Merge branch 'master' into ilm/update-condition-for-hiding-recommded-…
kibanamachine Feb 23, 2021
437962b
Merge branch 'master' into ilm/update-condition-for-hiding-recommded-…
kibanamachine Feb 25, 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 @@ -183,6 +183,13 @@ export const setup = async (arg?: {

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

const showDataAllocationOptions = (phase: Phases) => () => {
act(() => {
find(`${phase}-dataTierAllocationControls.dataTierSelect`).simulate('click');
});
component.update();
};

const createMinAgeActions = (phase: Phases) => {
return {
hasMinAgeInput: () => exists(`${phase}-selectedMinimumAge`),
Expand Down Expand Up @@ -379,6 +386,7 @@ export const setup = async (arg?: {
},
warm: {
enable: enable('warm'),
showDataAllocationOptions: showDataAllocationOptions('warm'),
...createMinAgeActions('warm'),
setReplicas: setReplicas('warm'),
hasErrorIndicator: () => exists('phaseErrorIndicator-warm'),
Expand All @@ -390,6 +398,7 @@ export const setup = async (arg?: {
},
cold: {
enable: enable('cold'),
showDataAllocationOptions: showDataAllocationOptions('cold'),
...createMinAgeActions('cold'),
setReplicas: setReplicas('cold'),
setFreeze,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -693,43 +693,52 @@ describe('<EditPolicy />', () => {
expect(find('cold-dataTierAllocationControls.dataTierSelect').text()).toContain('Off');
});
});
});

describe('searchable snapshot', () => {
describe('on cloud', () => {
describe('new policy', () => {
describe('using legacy data role config', () => {
beforeEach(async () => {
// simulate creating a new policy
httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('')]);
httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('my_policy')]);
httpRequestsMockHelpers.setListNodes({
isUsingDeprecatedDataRoleConfig: false,
nodesByAttributes: { test: ['123'] },
nodesByRoles: { data: ['123'] },
// On cloud, even if there are data_* roles set, the default, recommended allocation option should not
// be available.
nodesByRoles: { data_hot: ['123'] },
isUsingDeprecatedDataRoleConfig: true,
});
httpRequestsMockHelpers.setListSnapshotRepos({ repositories: ['found-snapshots'] });

await act(async () => {
testBed = await setup({ appServicesContext: { cloud: { isCloudEnabled: true } } });
testBed = await setup({
appServicesContext: {
cloud: {
isCloudEnabled: true,
},
license: licensingMock.createLicense({ license: { type: 'basic' } }),
},
});
});

const { component } = testBed;
component.update();
});
test('defaults searchable snapshot to true on cloud', async () => {
const { find, actions } = testBed;
await actions.cold.enable(true);
expect(
find('searchableSnapshotField-cold.searchableSnapshotToggle').props()['aria-checked']
).toBe(true);
test('removes default, recommended option', async () => {
const { actions, find } = testBed;
await actions.warm.enable(true);
actions.warm.showDataAllocationOptions();

expect(find('defaultDataAllocationOption').exists()).toBeFalsy();
expect(find('customDataAllocationOption').exists()).toBeTruthy();
expect(find('noneDataAllocationOption').exists()).toBeTruthy();
// Show the call-to-action for users to migrate their cluster to use node roles
expect(find('cloudDataTierCallout').exists()).toBeTruthy();
});
});
describe('existing policy', () => {
describe('using node roles', () => {
beforeEach(async () => {
httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('my_policy')]);
httpRequestsMockHelpers.setListNodes({
isUsingDeprecatedDataRoleConfig: false,
nodesByAttributes: { test: ['123'] },
nodesByRoles: { data: ['123'] },
nodesByRoles: { data_hot: ['123'] },
isUsingDeprecatedDataRoleConfig: false,
});
httpRequestsMockHelpers.setListSnapshotRepos({ repositories: ['found-snapshots'] });

Expand All @@ -740,19 +749,34 @@ describe('<EditPolicy />', () => {
const { component } = testBed;
component.update();
});
test('correctly sets snapshot repository default to "found-snapshots"', async () => {
const { actions } = testBed;

test('should show recommended, custom and "off" options on cloud with data roles', async () => {
const { actions, find } = testBed;

await actions.warm.enable(true);
actions.warm.showDataAllocationOptions();
expect(find('defaultDataAllocationOption').exists()).toBeTruthy();
expect(find('customDataAllocationOption').exists()).toBeTruthy();
expect(find('noneDataAllocationOption').exists()).toBeTruthy();
// We should not be showing the call-to-action for users to activate the cold tier on cloud
expect(find('cloudMissingColdTierCallout').exists()).toBeFalsy();
// Do not show the call-to-action for users to migrate their cluster to use node roles
expect(find('cloudDataTierCallout').exists()).toBeFalsy();
});

test('should show cloud notice when cold tier nodes do not exist', async () => {
const { actions, find } = testBed;
await actions.cold.enable(true);
await actions.cold.toggleSearchableSnapshot(true);
await actions.savePolicy();
const latestRequest = server.requests[server.requests.length - 1];
const request = JSON.parse(JSON.parse(latestRequest.requestBody).body);
expect(request.phases.cold.actions.searchable_snapshot.snapshot_repository).toEqual(
'found-snapshots'
);
expect(find('cloudMissingColdTierCallout').exists()).toBeTruthy();
// Assert that other notices are not showing
expect(find('defaultAllocationNotice').exists()).toBeFalsy();
expect(find('noNodeAttributesWarning').exists()).toBeFalsy();
});
});
});
});

describe('searchable snapshot', () => {
describe('on non-enterprise license', () => {
beforeEach(async () => {
httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('my_policy')]);
Expand Down Expand Up @@ -789,6 +813,64 @@ describe('<EditPolicy />', () => {
expect(actions.cold.searchableSnapshotDisabledDueToLicense()).toBeTruthy();
});
});

describe('on cloud', () => {
describe('new policy', () => {
beforeEach(async () => {
// simulate creating a new policy
httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('')]);
httpRequestsMockHelpers.setListNodes({
nodesByAttributes: { test: ['123'] },
nodesByRoles: { data: ['123'] },
isUsingDeprecatedDataRoleConfig: false,
});
httpRequestsMockHelpers.setListSnapshotRepos({ repositories: ['found-snapshots'] });

await act(async () => {
testBed = await setup({ appServicesContext: { cloud: { isCloudEnabled: true } } });
});

const { component } = testBed;
component.update();
});
test('defaults searchable snapshot to true on cloud', async () => {
const { find, actions } = testBed;
await actions.cold.enable(true);
expect(
find('searchableSnapshotField-cold.searchableSnapshotToggle').props()['aria-checked']
).toBe(true);
});
});
describe('existing policy', () => {
beforeEach(async () => {
httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('my_policy')]);
httpRequestsMockHelpers.setListNodes({
isUsingDeprecatedDataRoleConfig: false,
nodesByAttributes: { test: ['123'] },
nodesByRoles: { data_hot: ['123'] },
});
httpRequestsMockHelpers.setListSnapshotRepos({ repositories: ['found-snapshots'] });

await act(async () => {
testBed = await setup({ appServicesContext: { cloud: { isCloudEnabled: true } } });
});

const { component } = testBed;
component.update();
});
test('correctly sets snapshot repository default to "found-snapshots"', async () => {
const { actions } = testBed;
await actions.cold.enable(true);
await actions.cold.toggleSearchableSnapshot(true);
await actions.savePolicy();
const latestRequest = server.requests[server.requests.length - 1];
const request = JSON.parse(JSON.parse(latestRequest.requestBody).body);
expect(request.phases.cold.actions.searchable_snapshot.snapshot_repository).toEqual(
'found-snapshots'
);
});
});
});
});
describe('with rollover', () => {
beforeEach(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ describe('<EditPolicy /> node allocation', () => {
expect(actions.warm.hasDefaultAllocationWarning()).toBeTruthy();
});

test('shows default allocation notice when hot tier exists, but not warm tier', async () => {
test('when configuring warm phase shows default allocation notice when hot tier exists, but not warm tier', async () => {
httpRequestsMockHelpers.setListNodes({
nodesByAttributes: {},
nodesByRoles: { data_hot: ['test'], data_cold: ['test'] },
Expand Down Expand Up @@ -309,7 +309,7 @@ describe('<EditPolicy /> node allocation', () => {

describe('on cloud', () => {
describe('with deprecated data role config', () => {
test('should hide data tier option on cloud using legacy node role configuration', async () => {
test('should hide data tier option on cloud', async () => {
httpRequestsMockHelpers.setListNodes({
nodesByAttributes: { test: ['123'] },
// On cloud, if using legacy config there will not be any "data_*" roles set.
Expand All @@ -331,10 +331,29 @@ describe('<EditPolicy /> node allocation', () => {
expect(exists('customDataAllocationOption')).toBeTruthy();
expect(exists('noneDataAllocationOption')).toBeTruthy();
});

test('should ask users to migrate to node roles when on cloud using legacy data role', async () => {
httpRequestsMockHelpers.setListNodes({
nodesByAttributes: { test: ['123'] },
// On cloud, if using legacy config there will not be any "data_*" roles set.
nodesByRoles: { data: ['test'] },
isUsingDeprecatedDataRoleConfig: true,
});
await act(async () => {
testBed = await setup({ appServicesContext: { cloud: { isCloudEnabled: true } } });
});
const { actions, component, exists } = testBed;

component.update();
await actions.warm.enable(true);
expect(component.find('.euiLoadingSpinner').exists()).toBeFalsy();

expect(exists('cloudDataTierCallout')).toBeTruthy();
});
});

describe('with node role config', () => {
test('shows off, custom and data role options on cloud with data roles', async () => {
test('shows data role, custom and "off" options on cloud with data roles', async () => {
httpRequestsMockHelpers.setListNodes({
nodesByAttributes: { test: ['123'] },
nodesByRoles: { data: ['test'], data_hot: ['test'], data_warm: ['test'] },
Expand Down Expand Up @@ -372,7 +391,7 @@ describe('<EditPolicy /> node allocation', () => {
await actions.cold.enable(true);
expect(component.find('.euiLoadingSpinner').exists()).toBeFalsy();

expect(exists('cloudDataTierCallout')).toBeTruthy();
expect(exists('cloudMissingColdTierCallout')).toBeTruthy();
// Assert that other notices are not showing
expect(actions.cold.hasDefaultAllocationNotice()).toBeFalsy();
expect(actions.cold.hasNoNodeAttrsWarning()).toBeFalsy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,38 @@

import { i18n } from '@kbn/i18n';
import React, { FunctionComponent } from 'react';
import { EuiCallOut } from '@elastic/eui';
import { EuiCallOut, EuiLink } from '@elastic/eui';

const i18nTexts = {
title: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.title', {
defaultMessage: 'Create a cold tier',
defaultMessage: 'Migrate to data tiers',
}),
body: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.body', {
defaultMessage: 'Edit your Elastic Cloud deployment to set up a cold tier.',
defaultMessage: 'Migrate your Elastic Cloud deployment to use data tiers.',
}),
linkText: i18n.translate(
'xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.linkToCloudDeploymentDescription',
{ defaultMessage: 'View cloud deployment' }
),
};

export const CloudDataTierCallout: FunctionComponent = () => {
interface Props {
linkToCloudDeployment?: string;
}

/**
* A call-to-action for users to migrate to data tiers if their cluster is still running
* the deprecated node.data:true config.
*/
export const CloudDataTierCallout: FunctionComponent<Props> = ({ linkToCloudDeployment }) => {
return (
<EuiCallOut title={i18nTexts.title} data-test-subj="cloudDataTierCallout">
{i18nTexts.body}
{i18nTexts.body}{' '}
{Boolean(linkToCloudDeployment) && (
<EuiLink href={linkToCloudDeployment} external>
{i18nTexts.linkText}
</EuiLink>
)}
</EuiCallOut>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import { EuiCallOut } from '@elastic/eui';

import { PhaseWithAllocation, DataTierRole } from '../../../../../../../../../common/types';

import { AllocationNodeRole } from '../../../../../../../lib';

const i18nTextsNodeRoleToDataTier: Record<DataTierRole, string> = {
data_hot: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.dataTierHotLabel', {
defaultMessage: 'hot',
Expand Down Expand Up @@ -84,24 +82,13 @@ const i18nTexts = {

interface Props {
phase: PhaseWithAllocation;
targetNodeRole: AllocationNodeRole;
targetNodeRole: DataTierRole;
}

export const DefaultAllocationNotice: FunctionComponent<Props> = ({ phase, targetNodeRole }) => {
const content =
targetNodeRole === 'none' ? (
<EuiCallOut
data-test-subj="defaultAllocationWarning"
title={i18nTexts.warning[phase].title}
color="warning"
>
{i18nTexts.warning[phase].body}
</EuiCallOut>
) : (
<EuiCallOut data-test-subj="defaultAllocationNotice" title={i18nTexts.notice[phase].title}>
{i18nTexts.notice[phase].body(targetNodeRole)}
</EuiCallOut>
);

return content;
return (
<EuiCallOut data-test-subj="defaultAllocationNotice" title={i18nTexts.notice[phase].title}>
{i18nTexts.notice[phase].body(targetNodeRole)}
</EuiCallOut>
);
};
Loading