Skip to content

Commit

Permalink
[7.11] [ILM ] Fix logic for showing/hiding recommended allocation on …
Browse files Browse the repository at this point in the history
…Cloud (#90592) (#92852)

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

* updated logic for hiding recommended allocation options on cloud and moved tests over from legacy test folder

* added version check and tests for version check to enable pre v8 behaviour

* implement feedback to make tests more legible, fix test names and minor refactors

* added additional callout for data tier state, also added some new copy specific to the migration of a deployment on cloud

* remove unused stackVersion context value

* address windows max path length constraint

* - Fix botched conflict resolution!
- Addressed PR feedback, updated data allocation field for readability; added comments and refactored default allocation notice and warning
- Added one more test case for on cloud; when to show the call to migrate to node roles

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
# Conflicts:
#	x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/edit_policy.helpers.tsx
#	x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/reactive_form/node_allocation.test.ts

* remove async describe

* update component integration for 7.11 branch

* remove legacy, duplicate test

* remove unused variable
  • Loading branch information
jloleysens authored Feb 25, 2021
1 parent 9917d76 commit 3206cb8
Show file tree
Hide file tree
Showing 10 changed files with 261 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,13 @@ export const setup = async (arg?: { appServicesContext: Partial<AppServicesConte
component.update();
};

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

const setSelectedNodeAttribute = (phase: Phases) =>
createFormSetValueAction(`${phase}-selectedNodeAttrs`);

Expand Down Expand Up @@ -252,6 +259,7 @@ export const setup = async (arg?: { appServicesContext: Partial<AppServicesConte
},
warm: {
enable: enable('warm'),
showDataAllocationOptions: showDataAllocationOptions('warm'),
warmPhaseOnRollover,
setMinAgeValue: setMinAgeValue('warm'),
setMinAgeUnits: setMinAgeUnits('warm'),
Expand All @@ -266,6 +274,7 @@ export const setup = async (arg?: { appServicesContext: Partial<AppServicesConte
},
cold: {
enable: enable('cold'),
showDataAllocationOptions: showDataAllocationOptions('warm'),
setMinAgeValue: setMinAgeValue('cold'),
setMinAgeUnits: setMinAgeUnits('cold'),
setDataAllocation: setDataAllocation('cold'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,45 @@ describe('<EditPolicy />', () => {
expect(warmPhase.actions.migrate).toEqual({ enabled: false });
});

describe('legacy data role on cloud', () => {
beforeEach(async () => {
httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('my_policy')]);
httpRequestsMockHelpers.setListNodes({
nodesByAttributes: { test: ['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,
});

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

const { component } = testBed;
component.update();
});

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('node roles', () => {
beforeEach(async () => {
httpRequestsMockHelpers.setLoadPolicies([POLICY_WITH_NODE_ROLE_ALLOCATION]);
Expand Down Expand Up @@ -669,6 +708,40 @@ describe('<EditPolicy />', () => {
}
`);
});

describe('on cloud', () => {
beforeEach(async () => {
httpRequestsMockHelpers.setLoadPolicies([getDefaultHotPhasePolicy('my_policy')]);
httpRequestsMockHelpers.setListNodes({
nodesByAttributes: { test: ['123'] },
nodesByRoles: { data_hot: ['123'] },
isUsingDeprecatedDataRoleConfig: false,
});

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

const { component } = testBed;
component.update();
});

test('should show cloud notice when cold tier nodes do not exist', async () => {
const { actions, find } = testBed;
await actions.cold.enable(true);
expect(find('cloudMissingColdTierCallout').exists()).toBeTruthy();
// Assert that other notices are not showing
expect(find('defaultAllocationNotice').exists()).toBeFalsy();
expect(find('noNodeAttributesWarning').exists()).toBeFalsy();
});
});
});

describe('node attr and none', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -905,23 +905,6 @@ describe('edit policy', () => {
// We should not be showing the call-to-action for users to activate data tiers in cloud
expect(findTestSubject(rendered, 'cloudDataTierCallout').exists()).toBeFalsy();
});

test('should show cloud notice when cold tier nodes do not exist', async () => {
http.setupNodeListResponse({
nodesByAttributes: {},
nodesByRoles: { data: ['test'], data_hot: ['test'], data_warm: ['test'] },
isUsingDeprecatedDataRoleConfig: false,
});
const rendered = mountWithIntl(component);
await noRollover(rendered);
await setPolicyName(rendered, 'mypolicy');
await activatePhase(rendered, 'cold');
expect(rendered.find('.euiLoadingSpinner').exists()).toBeFalsy();
expect(findTestSubject(rendered, 'cloudDataTierCallout').exists()).toBeTruthy();
// Assert that other notices are not showing
expect(findTestSubject(rendered, 'defaultAllocationNotice').exists()).toBeFalsy();
expect(findTestSubject(rendered, 'noNodeAttributesWarning').exists()).toBeFalsy();
});
});
});
});
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>
);
};
Original file line number Diff line number Diff line change
@@ -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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

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

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

const i18nTexts = {
warning: {
warm: {
title: i18n.translate(
'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableTitle',
{ defaultMessage: 'No nodes assigned to the warm tier' }
),
body: i18n.translate(
'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotAvailableBody',
{
defaultMessage:
'Assign at least one node to the warm or hot tier to use role-based allocation. The policy will fail to complete allocation if there are no available nodes.',
}
),
},
cold: {
title: i18n.translate(
'xpack.indexLifecycleMgmt.coldPhase.dataTier.defaultAllocationNotAvailableTitle',
{ defaultMessage: 'No nodes assigned to the cold tier' }
),
body: i18n.translate(
'xpack.indexLifecycleMgmt.coldPhase.dataTier.defaultAllocationNotAvailableBody',
{
defaultMessage:
'Assign at least one node to the cold, warm, or hot tier to use role-based allocation. The policy will fail to complete allocation if there are no available nodes.',
}
),
},
},
};

interface Props {
phase: PhaseWithAllocation;
}

export const DefaultAllocationWarning: FunctionComponent<Props> = ({ phase }) => {
return (
<EuiCallOut
data-test-subj="defaultAllocationWarning"
title={i18nTexts.warning[phase].title}
color="warning"
>
{i18nTexts.warning[phase].body}
</EuiCallOut>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ export { DataTierAllocation } from './data_tier_allocation';

export { DefaultAllocationNotice } from './default_allocation_notice';

export { DefaultAllocationWarning } from './default_allocation_warning';

export { NoNodeAttributesWarning } from './no_node_attributes_warning';

export { MissingColdTierCallout } from './missing_cold_tier_callout';

export { CloudDataTierCallout } from './cloud_data_tier_callout';

export { LoadingError } from './loading_error';
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

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

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

interface Props {
linkToCloudDeployment?: string;
}

/**
* A call-to-action for users to activate their cold tier slider to provision cold tier nodes.
* This may need to be change when we have autoscaling enabled on a cluster because nodes may not
* yet exist, but will automatically be provisioned.
*/
export const MissingColdTierCallout: FunctionComponent<Props> = ({ linkToCloudDeployment }) => {
return (
<EuiCallOut title={i18nTexts.title} data-test-subj="cloudMissingColdTierCallout">
{i18nTexts.body}{' '}
{Boolean(linkToCloudDeployment) && (
<EuiLink href={linkToCloudDeployment} external>
{i18nTexts.linkText}
</EuiLink>
)}
</EuiCallOut>
);
};
Loading

0 comments on commit 3206cb8

Please sign in to comment.