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] Add warnings for managed system policies #132269

Merged
merged 11 commits into from
May 20, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
*/

import React, { FunctionComponent, useState } from 'react';
import { EuiLink, EuiText } from '@elastic/eui';
import { EuiCallOut, EuiLink, EuiText, EuiSpacer } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { useEditPolicyContext } from '../edit_policy_context';
import { getIndicesListPath } from '../../../services/navigation';
import { useKibana } from '../../../../shared_imports';
import { IndexTemplatesFlyout } from '../../../components/index_templates_flyout';

export const EditWarning: FunctionComponent = () => {
const { isNewPolicy, indices, indexTemplates, policyName } = useEditPolicyContext();
const { isNewPolicy, indices, indexTemplates, policyName, policy } = useEditPolicyContext();
const {
services: { getUrlForApp },
} = useKibana();
Expand Down Expand Up @@ -67,6 +67,8 @@ export const EditWarning: FunctionComponent = () => {
) : (
indexTemplatesLink
);
const isManagedPolicy = policy?._meta?.managed;

return (
<>
{isIndexTemplatesFlyoutShown && (
Expand All @@ -77,6 +79,29 @@ export const EditWarning: FunctionComponent = () => {
/>
)}
<EuiText data-test-subj="editWarning">
{isManagedPolicy && (
<>
<EuiCallOut
title={
<FormattedMessage
id="xpack.indexLifecycleMgmt.editPolicyModal.proceedWithCautionCallOutTitle"
defaultMessage="Editing a managed policy can break Kibana"
/>
}
color="danger"
iconType="alert"
data-test-subj="editManagedPolicyCallOut"
>
<p>
<FormattedMessage
id="xpack.indexLifecycleMgmt.editPolicyModal.proceedWithCautionCallOutDescription"
defaultMessage="Managed policies are critical for internal operations."
/>
</p>
</EuiCallOut>
<EuiSpacer />
</>
)}
<p>
<strong>
<FormattedMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import React, { Component } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { EuiConfirmModal } from '@elastic/eui';
import { EuiCallOut, EuiCheckbox, EuiConfirmModal } from '@elastic/eui';

import { PolicyFromES } from '../../../../../common/types';
import { toasts } from '../../../services/notification';
Expand All @@ -21,6 +21,16 @@ interface Props {
onCancel: () => void;
}
export class ConfirmDelete extends Component<Props> {
public state = {
isDeleteConfirmed: false,
};

setIsDeleteConfirmed = (confirmed: boolean) => {
this.setState({
isDeleteConfirmed: confirmed,
});
};

deletePolicy = async () => {
const { policyToDelete, callback } = this.props;
const policyName = policyToDelete.name;
Expand All @@ -43,8 +53,12 @@ export class ConfirmDelete extends Component<Props> {
callback();
}
};
isPolicyPolicy = true;
render() {
const { policyToDelete, onCancel } = this.props;
const { isDeleteConfirmed } = this.state;
const isManagedPolicy = policyToDelete.policy?._meta?.managed;

const title = i18n.translate('xpack.indexLifecycleMgmt.confirmDelete.title', {
defaultMessage: 'Delete policy "{name}"',
values: { name: policyToDelete.name },
Expand All @@ -68,13 +82,47 @@ export class ConfirmDelete extends Component<Props> {
/>
}
buttonColor="danger"
confirmButtonDisabled={isManagedPolicy ? !isDeleteConfirmed : false}
>
<div>
<FormattedMessage
id="xpack.indexLifecycleMgmt.confirmDelete.undoneWarning"
defaultMessage="You can't recover a deleted policy."
/>
</div>
{isManagedPolicy ? (
<EuiCallOut
title={
<FormattedMessage
id="xpack.indexLifecycleMgmt.deletePolicyModal.proceedWithCautionCallOutTitle"
defaultMessage="Deleting a managed policy can break Kibana"
/>
}
color="danger"
iconType="alert"
data-test-subj="deleteManagedPolicyCallOut"
>
<p>
<FormattedMessage
id="xpack.indexLifecycleMgmt.deletePolicyModal.proceedWithCautionCallOutDescription"
defaultMessage="Managed policies are critical for internal operations.
If you delete this managed policy, you can’t recover it."
/>
</p>
<EuiCheckbox
id="confirmDeletePolicyCheckbox"
label={
<FormattedMessage
id="xpack.indexLifecycleMgmt.deletePolicyModal.confirmDeleteCheckboxLabel"
defaultMessage="I understand the consequences of deleting a managed policy"
/>
}
checked={isDeleteConfirmed}
onChange={(e) => this.setIsDeleteConfirmed(e.target.checked)}
/>
</EuiCallOut>
) : (
<div>
<FormattedMessage
id="xpack.indexLifecycleMgmt.confirmDelete.undoneWarning"
defaultMessage="You can't recover a deleted policy."
/>
</div>
)}
</EuiConfirmModal>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,17 @@
* 2.0.
*/

import React from 'react';
import { EuiButtonEmpty, EuiLink, EuiInMemoryTable, EuiToolTip, EuiButtonIcon } from '@elastic/eui';
import React, { useMemo, useState } from 'react';
import {
EuiButtonEmpty,
EuiLink,
EuiInMemoryTable,
EuiToolTip,
EuiButtonIcon,
EuiBadge,
EuiFlexItem,
EuiSwitch,
} from '@elastic/eui';

import { i18n } from '@kbn/i18n';

Expand All @@ -15,6 +24,7 @@ import { METRIC_TYPE } from '@kbn/analytics';
import { useHistory } from 'react-router-dom';
import { EuiBasicTableColumn } from '@elastic/eui/src/components/basic_table/basic_table';
import { reactRouterNavigate } from '@kbn/kibana-react-plugin/public';
import { FormattedMessage } from '@kbn/i18n-react';
import { PolicyFromES } from '../../../../../common/types';
import { useKibana } from '../../../../shared_imports';
import { getIndicesListPath, getPolicyEditPath } from '../../../services/navigation';
Expand Down Expand Up @@ -45,6 +55,19 @@ const actionTooltips = {
),
};

const managedPolicyTooltips = {
badge: i18n.translate('xpack.indexLifecycleMgmt.policyTable.templateBadgeType.managedLabel', {
defaultMessage: 'Managed',
}),
badgeTooltip: i18n.translate(
'xpack.indexLifecycleMgmt.policyTable.templateBadgeType.managedDescription',
{
defaultMessage:
'This policy is preconfigured and managed by Elastic; editing or deleting this policy might break Kibana.',
}
),
};

interface Props {
policies: PolicyFromES[];
}
Expand All @@ -54,8 +77,36 @@ export const PolicyTable: React.FunctionComponent<Props> = ({ policies }) => {
const {
services: { getUrlForApp },
} = useKibana();

const [managedPoliciesVisible, setManagedPoliciesVisible] = useState<boolean>(false);
const { setListAction } = usePolicyListContext();
const searchOptions = useMemo(
() => ({
box: { incremental: true, 'data-test-subj': 'ilmSearchBar' },
toolsRight: (
<EuiFlexItem grow={false}>
<EuiSwitch
Copy link
Contributor

Choose a reason for hiding this comment

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

As discussed, would be nice to remember the setting of this switch, so that it doesn't revert to 'off' after viewing or editing a managed policy.

id="checkboxShowHiddenIndices"
data-test-subj="includeHiddenPoliciesToggle"
checked={managedPoliciesVisible}
onChange={(event) => setManagedPoliciesVisible(event.target.checked)}
label={
<FormattedMessage
id="xpack.indexLifecycleMgmt.policyTable.hiddenPoliciesSwitchLabel"
defaultMessage="Include managed system policies"
/>
}
/>
</EuiFlexItem>
),
}),
[managedPoliciesVisible]
);

const filteredPolicies = useMemo(() => {
return managedPoliciesVisible
? policies
: policies.filter((item) => !item.policy?._meta?.managed);
}, [policies, managedPoliciesVisible]);

const columns: Array<EuiBasicTableColumn<PolicyFromES>> = [
{
Expand All @@ -65,17 +116,31 @@ export const PolicyTable: React.FunctionComponent<Props> = ({ policies }) => {
defaultMessage: 'Name',
}),
sortable: true,
render: (value: string) => {
render: (value: string, item) => {
const isManaged = item.policy?._meta?.managed;
return (
<EuiLink
className="eui-textBreakAll"
data-test-subj="policyTablePolicyNameLink"
{...reactRouterNavigate(history, getPolicyEditPath(value), () =>
trackUiMetric(METRIC_TYPE.CLICK, UIM_EDIT_CLICK)
<>
<EuiLink
className="eui-textBreakAll"
data-test-subj="policyTablePolicyNameLink"
{...reactRouterNavigate(history, getPolicyEditPath(value), () =>
trackUiMetric(METRIC_TYPE.CLICK, UIM_EDIT_CLICK)
)}
>
{value}
</EuiLink>

{isManaged && (
<>
&nbsp;
<EuiToolTip content={managedPolicyTooltips.badgeTooltip}>
<EuiBadge color="hollow" data-test-subj="templateTypeBadge">
{managedPolicyTooltips.badge}
</EuiBadge>
</EuiToolTip>
</>
)}
>
{value}
</EuiLink>
</>
);
},
},
Expand Down Expand Up @@ -191,11 +256,9 @@ export const PolicyTable: React.FunctionComponent<Props> = ({ policies }) => {
direction: 'asc',
},
}}
search={{
box: { incremental: true, 'data-test-subj': 'ilmSearchBar' },
}}
search={searchOptions}
tableLayout="auto"
items={policies}
items={filteredPolicies}
columns={columns}
rowProps={(policy: PolicyFromES) => ({ 'data-test-subj': `policyTableRow-${policy.name}` })}
/>
Expand Down