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] Cloud-specific changes for 7.10 #79650

Merged
merged 15 commits into from
Oct 13, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
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 @@ -21,8 +21,10 @@ import {
fatalErrorsServiceMock,
} from '../../../../../src/core/public/mocks';
import { usageCollectionPluginMock } from '../../../../../src/plugins/usage_collection/public/mocks';
import { CloudSetup } from '../../../cloud/public';

import { EditPolicy } from '../../public/application/sections/edit_policy/edit_policy';
import { KibanaContextProvider } from '../../public/shared_imports';
import { init as initHttp } from '../../public/application/services/http';
import { init as initUiMetric } from '../../public/application/services/ui_metric';
import { init as initNotification } from '../../public/application/services/notification';
Expand Down Expand Up @@ -148,7 +150,14 @@ const save = (rendered: ReactWrapper) => {
describe('edit policy', () => {
beforeEach(() => {
component = (
<EditPolicy history={history} getUrlForApp={jest.fn()} policies={policies} policyName={''} />
<KibanaContextProvider services={{ cloud: { isCloudEnabled: false } as CloudSetup }}>
<EditPolicy
history={history}
getUrlForApp={jest.fn()}
policies={policies}
policyName={''}
/>
</KibanaContextProvider>
);

({ http } = editPolicyHelpers.setup());
Expand Down Expand Up @@ -679,4 +688,38 @@ describe('edit policy', () => {
expectedErrorMessages(rendered, [positiveNumberRequiredMessage]);
});
});
describe('on cloud', () => {
beforeEach(() => {
component = (
<KibanaContextProvider services={{ cloud: { isCloudEnabled: true } as CloudSetup }}>
<EditPolicy
history={history}
getUrlForApp={jest.fn()}
policies={policies}
policyName={''}
/>
</KibanaContextProvider>
);
({ http } = editPolicyHelpers.setup());
({ server, httpRequestsMockHelpers } = http);
server.respondImmediately = true;

httpRequestsMockHelpers.setPoliciesResponse(policies);
});
test('should show cloud notice cold tier nodes do not exist', async () => {
http.setupNodeListResponse({
nodesByAttributes: {},
nodesByRoles: { data: ['test'], data_hot: ['test'], data_warm: ['test'] },
});
const rendered = mountWithIntl(component);
noRollover(rendered);
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();
});
});
});
1 change: 1 addition & 0 deletions x-pack/plugins/index_lifecycle_management/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"features"
],
"optionalPlugins": [
"cloud",
"usageCollection",
"indexManagement",
"home"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { I18nStart, ScopedHistory, ApplicationStart } from 'kibana/public';
import { UnmountCallback } from 'src/core/public';
import { CloudSetup } from '../../../cloud/public';

import { KibanaContextProvider } from '../shared_imports';

import { App } from './app';

Expand All @@ -16,11 +19,14 @@ export const renderApp = (
I18nContext: I18nStart['Context'],
history: ScopedHistory,
navigateToApp: ApplicationStart['navigateToApp'],
getUrlForApp: ApplicationStart['getUrlForApp']
getUrlForApp: ApplicationStart['getUrlForApp'],
cloud?: CloudSetup
): UnmountCallback => {
render(
<I18nContext>
<App history={history} navigateToApp={navigateToApp} getUrlForApp={getUrlForApp} />
<KibanaContextProvider services={{ cloud }}>
<App history={history} navigateToApp={navigateToApp} getUrlForApp={getUrlForApp} />
</KibanaContextProvider>
</I18nContext>,
element
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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 { i18n } from '@kbn/i18n';
import React, { FunctionComponent } from 'react';
import { EuiCallOut } from '@elastic/eui';

const i18nTexts = {
title: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.title', {
defaultMessage: 'No cold tier found',
}),
body: i18n.translate('xpack.indexLifecycleMgmt.editPolicy.cloudDataTierCallout.body', {
defaultMessage:
'Data in this phase will be allocated to hot and warm tier nodes. Go to the Cloud UI to create a cold tier.',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might need some writer's eyes on this copy. For example, I'd expect to refer to "Elastic Cloud" instead of "Cloud UI". Can we make that a link to https://cloud.elastic.co/home?

}),
};

export const CloudDataTierCallout: FunctionComponent = () => {
return (
<EuiCallOut title={i18nTexts.title} data-test-subj="cloudDataTierCallout">
{i18nTexts.body}
</EuiCallOut>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

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

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

Expand Down Expand Up @@ -102,10 +102,5 @@ export const DefaultAllocationNotice: FunctionComponent<Props> = ({ phase, targe
</EuiCallOut>
);

return (
<>
<EuiSpacer size="s" />
{content}
</>
);
return content;
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export { NodeAttrsDetails } from './node_attrs_details';
export { DataTierAllocation } from './data_tier_allocation';
export { DefaultAllocationNotice } from './default_allocation_notice';
export { NoNodeAttributesWarning } from './no_node_attributes_warning';
export { CloudDataTierCallout } from './cloud_data_tier_callout';
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

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

import { PhaseWithAllocation } from '../../../../../../common/types';
Expand Down Expand Up @@ -38,16 +38,13 @@ export const NoNodeAttributesWarning: FunctionComponent<{ phase: PhaseWithAlloca
phase,
}) => {
return (
<>
<EuiSpacer size="s" />
<EuiCallOut
data-test-subj="noNodeAttributesWarning"
style={{ maxWidth: 400 }}
title={i18nTexts.title}
color="warning"
>
{i18nTexts[phase].body}
</EuiCallOut>
</>
<EuiCallOut
data-test-subj="noNodeAttributesWarning"
style={{ maxWidth: 400 }}
title={i18nTexts.title}
color="warning"
>
{i18nTexts[phase].body}
</EuiCallOut>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

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

import { useKibana } from '../../../../../shared_imports';
import { PhaseWithAllocationAction, PhaseWithAllocation } from '../../../../../../common/types';
import { PhaseValidationErrors } from '../../../../services/policies/policy_validation';
import { getAvailableNodeRoleForPhase } from '../../../../lib/data_tiers';
Expand All @@ -18,6 +19,7 @@ import {
DefaultAllocationNotice,
NoNodeAttributesWarning,
NodesDataProvider,
CloudDataTierCallout,
} from '../../components/data_tier_allocation';

const i18nTexts = {
Expand Down Expand Up @@ -46,25 +48,33 @@ export const DataTierAllocationField: FunctionComponent<Props> = ({
isShowingErrors,
errors,
}) => {
const {
services: { cloud },
} = useKibana();
return (
<NodesDataProvider>
{(nodesData) => {
const hasNodeAttrs = Boolean(Object.keys(nodesData.nodesByAttributes ?? {}).length);
{({ nodesByRoles, nodesByAttributes }) => {
const hasNodeAttrs = Boolean(Object.keys(nodesByAttributes ?? {}).length);

const renderDefaultAllocationNotice = () => {
if (phaseData.dataTierAllocationType !== 'default') {
return null;
}

const allocationNodeRole = getAvailableNodeRoleForPhase(phase, nodesData.nodesByRoles);
const allocationNodeRole = getAvailableNodeRoleForPhase(phase, nodesByRoles);
if (
allocationNodeRole !== 'none' &&
isNodeRoleFirstPreference(phase, allocationNodeRole)
) {
return null;
}

return <DefaultAllocationNotice phase={phase} targetNodeRole={allocationNodeRole} />;
return (
<>
<EuiSpacer size="s" />
<DefaultAllocationNotice phase={phase} targetNodeRole={allocationNodeRole} />
</>
);
};

const renderNodeAttributesWarning = () => {
Expand All @@ -74,7 +84,37 @@ export const DataTierAllocationField: FunctionComponent<Props> = ({
if (hasNodeAttrs) {
return null;
}
return <NoNodeAttributesWarning phase={phase} />;
return (
<>
<EuiSpacer size="s" />
<NoNodeAttributesWarning phase={phase} />
</>
);
};

const renderCloudCallout = () => {
const isCloudEnabled = cloud?.isCloudEnabled ?? false;
if (
phase !== 'cold' ||
!isCloudEnabled ||
phaseData.dataTierAllocationType !== 'default'
) {
return null;
}

/**
* Check whether there are any data_cold tier roles
*/
if (nodesByRoles.data_cold?.length) {
return null;
}

return (
<>
<EuiSpacer size="s" />
<CloudDataTierCallout />
</>
);
};

return (
Expand All @@ -92,12 +132,13 @@ export const DataTierAllocationField: FunctionComponent<Props> = ({
setPhaseData={setPhaseData}
phaseData={phaseData}
isShowingErrors={isShowingErrors}
nodes={nodesData.nodesByAttributes}
nodes={nodesByAttributes}
/>

{/* Data tier related warnings */}
{/* Data tier related warnings and call-to-action notices */}
{renderDefaultAllocationNotice()}
{renderNodeAttributesWarning()}
{renderCloudCallout()}
</>
</EuiFormRow>
</EuiDescribedFormGroup>
Expand Down
5 changes: 3 additions & 2 deletions x-pack/plugins/index_lifecycle_management/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class IndexLifecycleManagementPlugin {
getStartServices,
} = coreSetup;

const { usageCollection, management, indexManagement, home } = plugins;
const { usageCollection, management, indexManagement, home, cloud } = plugins;

// Initialize services even if the app isn't mounted, because they're used by index management extensions.
initHttp(http);
Expand Down Expand Up @@ -65,7 +65,8 @@ export class IndexLifecycleManagementPlugin {
I18nContext,
history,
navigateToApp,
getUrlForApp
getUrlForApp,
cloud
);

return () => {
Expand Down
10 changes: 10 additions & 0 deletions x-pack/plugins/index_lifecycle_management/public/shared_imports.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* 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 { AppServicesContext } from './types';
import { useKibana as _useKibana } from '../../../../src/plugins/kibana_react/public';

export { KibanaContextProvider } from '../../../../src/plugins/kibana_react/public';
export const useKibana = () => _useKibana<AppServicesContext>();
6 changes: 6 additions & 0 deletions x-pack/plugins/index_lifecycle_management/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import { HomePublicPluginSetup } from '../../../../src/plugins/home/public';
import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public';
import { ManagementSetup } from '../../../../src/plugins/management/public';
import { IndexManagementPluginSetup } from '../../index_management/public';
import { CloudSetup } from '../../cloud/public';

export interface PluginsDependencies {
usageCollection?: UsageCollectionSetup;
management: ManagementSetup;
cloud?: CloudSetup;
indexManagement?: IndexManagementPluginSetup;
home?: HomePublicPluginSetup;
}
Expand All @@ -21,3 +23,7 @@ export interface ClientConfigType {
enabled: boolean;
};
}

export interface AppServicesContext {
cloud?: CloudSetup;
}