Skip to content

Commit

Permalink
[ILM] Update show/hide data tier logic on cloud (#81455)
Browse files Browse the repository at this point in the history
* Update show/hide data tier logic

only show data tier options on cloud if the cluster is not using
the deprecated node.data config and there is a data_* role
present. this will likely be a role like data_content which will
ensure that the cluster is configured with the new data tier
roles.

* refactor node role types for clarity

* added comment

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
jloleysens and kibanamachine authored Oct 26, 2020
1 parent ab4dfcf commit 0a0773a
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,8 @@ describe('edit policy', () => {
test('should hide data tier option on cloud using legacy node role configuration', async () => {
http.setupNodeListResponse({
nodesByAttributes: { test: ['123'] },
nodesByRoles: { data: ['test'], data_hot: ['test'], data_warm: ['test'] },
// On cloud, if using legacy config there will not be any "data_*" roles set.
nodesByRoles: { data: ['test'] },
isUsingDeprecatedDataRoleConfig: true,
});
const rendered = mountWithIntl(component);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@

// Order of node roles matters here, the warm phase prefers allocating data
// to the data_warm role.
import { NodeDataRole, PhaseWithAllocation } from '../types';
import { DataTierRole, PhaseWithAllocation } from '../types';

const WARM_PHASE_NODE_PREFERENCE: NodeDataRole[] = ['data_warm', 'data_hot'];
const WARM_PHASE_NODE_PREFERENCE: DataTierRole[] = ['data_warm', 'data_hot'];

const COLD_PHASE_NODE_PREFERENCE: NodeDataRole[] = ['data_cold', 'data_warm', 'data_hot'];
const COLD_PHASE_NODE_PREFERENCE: DataTierRole[] = ['data_cold', 'data_warm', 'data_hot'];

export const phaseToNodePreferenceMap: Record<PhaseWithAllocation, NodeDataRole[]> = Object.freeze({
export const phaseToNodePreferenceMap: Record<PhaseWithAllocation, DataTierRole[]> = Object.freeze({
warm: WARM_PHASE_NODE_PREFERENCE,
cold: COLD_PHASE_NODE_PREFERENCE,
});
4 changes: 2 additions & 2 deletions x-pack/plugins/index_lifecycle_management/common/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { NodeDataRoleWithCatchAll } from '.';
import { AnyDataRole } from '.';

export interface ListNodesRouteResponse {
nodesByAttributes: { [attributePair: string]: string[] };
nodesByRoles: { [role in NodeDataRoleWithCatchAll]?: string[] };
nodesByRoles: { [role in AnyDataRole]?: string[] };

/**
* A flag to indicate whether a node is using `settings.node.data` which is the now deprecated way cloud configured
Expand Down
17 changes: 13 additions & 4 deletions x-pack/plugins/index_lifecycle_management/common/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,17 @@ export * from './api';
export * from './policies';

/**
* These roles reflect how nodes are stratified into different data tiers. The "data" role
* is a catch-all that can be used to store data in any phase.
* These roles reflect how nodes are stratified into different data tiers.
*/
export type NodeDataRole = 'data_hot' | 'data_warm' | 'data_cold';
export type NodeDataRoleWithCatchAll = 'data' | NodeDataRole;
export type DataTierRole = 'data_hot' | 'data_warm' | 'data_cold';

/**
* The "data_content" role can store all data the ES stack uses for feature
* functionality like security-related indices.
*/
export type DataRole = 'data_content' | DataTierRole;

/**
* The "data" role can store data allocated to any tier.
*/
export type AnyDataRole = 'data' | DataRole;
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
*/

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

import { phaseToNodePreferenceMap } from '../../../../common/constants';

export type AllocationNodeRole = NodeDataRole | 'none';
export type AllocationNodeRole = DataTierRole | 'none';

/**
* Given a phase and current cluster node roles, determine which nodes the phase
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/

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

export const isNodeRoleFirstPreference = (phase: PhaseWithAllocation, nodeRole: NodeDataRole) => {
export const isNodeRoleFirstPreference = (phase: PhaseWithAllocation, nodeRole: DataTierRole) => {
return phaseToNodePreferenceMap[phase][0] === nodeRole;
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import { i18n } from '@kbn/i18n';
import React, { FunctionComponent } from 'react';
import { EuiCallOut } from '@elastic/eui';

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

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

const i18nTextsNodeRoleToDataTier: Record<NodeDataRole, string> = {
const i18nTextsNodeRoleToDataTier: Record<DataTierRole, string> = {
data_hot: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.dataTierHotLabel', {
defaultMessage: 'hot',
}),
Expand All @@ -31,7 +31,7 @@ const i18nTexts = {
'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm.title',
{ defaultMessage: 'No nodes assigned to the warm tier' }
),
body: (nodeRole: NodeDataRole) =>
body: (nodeRole: DataTierRole) =>
i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.warm', {
defaultMessage:
'This policy will move data in the warm phase to {tier} tier nodes instead.',
Expand All @@ -43,7 +43,7 @@ const i18nTexts = {
'xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold.title',
{ defaultMessage: 'No nodes assigned to the cold tier' }
),
body: (nodeRole: NodeDataRole) =>
body: (nodeRole: DataTierRole) =>
i18n.translate('xpack.indexLifecycleMgmt.warmPhase.dataTier.defaultAllocationNotice.cold', {
defaultMessage:
'This policy will move data in the cold phase to {tier} tier nodes instead.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,19 @@ export const DataTierAllocationField: FunctionComponent<Props> = ({
return (
<NodesDataProvider>
{({ nodesByRoles, nodesByAttributes, isUsingDeprecatedDataRoleConfig }) => {
const hasDataNodeRoles = Object.keys(nodesByRoles).some((nodeRole) =>
// match any of the "data_" roles, including data_content.
nodeRole.trim().startsWith('data_')
);
const hasNodeAttrs = Boolean(Object.keys(nodesByAttributes ?? {}).length);

const renderNotice = () => {
switch (phaseData.dataTierAllocationType) {
case 'default':
const isCloudEnabled = cloud?.isCloudEnabled ?? false;
if (isCloudEnabled && phase === 'cold') {
const isUsingNodeRolesAllocation = !isUsingDeprecatedDataRoleConfig;
const isUsingNodeRolesAllocation =
!isUsingDeprecatedDataRoleConfig && hasDataNodeRoles;
const hasNoNodesWithNodeRole = !nodesByRoles.data_cold?.length;

if (isUsingNodeRolesAllocation && hasNoNodesWithNodeRole) {
Expand Down Expand Up @@ -120,9 +125,9 @@ export const DataTierAllocationField: FunctionComponent<Props> = ({
phaseData={phaseData}
isShowingErrors={isShowingErrors}
nodes={nodesByAttributes}
disableDataTierOption={
!!(isUsingDeprecatedDataRoleConfig && cloud?.isCloudEnabled)
}
disableDataTierOption={Boolean(
cloud?.isCloudEnabled && !hasDataNodeRoles && isUsingDeprecatedDataRoleConfig
)}
/>

{/* Data tier related warnings and call-to-action notices */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

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

import { RouteDependencies } from '../../../types';
import { addBasePath } from '../../../services';
Expand Down Expand Up @@ -39,10 +39,10 @@ export function convertSettingsIntoLists(
}
}

const dataRoles = nodeSettings.roles.filter((r) => r.startsWith('data')) as NodeDataRole[];
const dataRoles = nodeSettings.roles.filter((r) => r.startsWith('data')) as DataTierRole[];
for (const role of dataRoles) {
accum.nodesByRoles[role as NodeDataRole] = accum.nodesByRoles[role] ?? [];
accum.nodesByRoles[role as NodeDataRole]!.push(nodeId);
accum.nodesByRoles[role as DataTierRole] = accum.nodesByRoles[role] ?? [];
accum.nodesByRoles[role as DataTierRole]!.push(nodeId);
}

// If we detect a single node using legacy "data:true" setting we know we are not using data roles for
Expand Down

0 comments on commit 0a0773a

Please sign in to comment.