Skip to content

Commit d67c527

Browse files
authored
[Index management] Support DS failure store configuration (#223389)
1 parent aed9f98 commit d67c527

File tree

20 files changed

+523
-20
lines changed

20 files changed

+523
-20
lines changed

src/platform/packages/shared/kbn-doc-links/src/get_doc_links.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D
309309
docsBase: `${ELASTIC_DOCS}solutions/search`,
310310
asyncSearch: `${ELASTIC_DOCS}solutions/search/async-search-api`,
311311
dataStreams: `${ELASTIC_DOCS}manage-data/data-store/data-streams`,
312+
dataStreamsFailureStore: `${ELASTIC_DOCS}manage-data/data-store/data-streams/failure-store`,
312313
deprecationLogging: `${ELASTIC_DOCS}deploy-manage/monitor/logging-configuration/update-elasticsearch-logging-levels#deprecation-logging`,
313314
createEnrichPolicy: isServerless
314315
? `${ELASTICSEARCH_SERVERLESS_APIS}operation/operation-enrich-put-policy`

x-pack/platform/plugins/shared/index_management/__jest__/client_integration/home/data_streams_tab.helpers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@ export const createDataStreamPayload = (dataStream: Partial<DataStream>): DataSt
308308
privileges: {
309309
delete_index: true,
310310
manage_data_stream_lifecycle: true,
311+
read_failure_store: true,
311312
},
312313
hidden: false,
313314
lifecycle: {

x-pack/platform/plugins/shared/index_management/__jest__/client_integration/home/data_streams_tab.test.ts

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -460,11 +460,19 @@ describe('Data Streams tab', () => {
460460

461461
const ds1 = createDataStreamPayload({
462462
name: 'dataStream1',
463-
privileges: { delete_index: true, manage_data_stream_lifecycle: true },
463+
privileges: {
464+
delete_index: true,
465+
manage_data_stream_lifecycle: true,
466+
read_failure_store: true,
467+
},
464468
});
465469
const ds2 = createDataStreamPayload({
466470
name: 'dataStream2',
467-
privileges: { delete_index: true, manage_data_stream_lifecycle: true },
471+
privileges: {
472+
delete_index: true,
473+
manage_data_stream_lifecycle: true,
474+
read_failure_store: true,
475+
},
468476
});
469477

470478
setLoadDataStreamsResponse([ds1, ds2]);
@@ -1217,20 +1225,36 @@ describe('Data Streams tab', () => {
12171225

12181226
const dataStreamFullPermissions = createDataStreamPayload({
12191227
name: 'dataStreamFullPermissions',
1220-
privileges: { delete_index: true, manage_data_stream_lifecycle: true },
1228+
privileges: {
1229+
delete_index: true,
1230+
manage_data_stream_lifecycle: true,
1231+
read_failure_store: true,
1232+
},
12211233
});
12221234
const dataStreamNoDelete = createDataStreamPayload({
12231235
name: 'dataStreamNoDelete',
1224-
privileges: { delete_index: false, manage_data_stream_lifecycle: true },
1236+
privileges: {
1237+
delete_index: false,
1238+
manage_data_stream_lifecycle: true,
1239+
read_failure_store: true,
1240+
},
12251241
});
12261242
const dataStreamNoEditRetention = createDataStreamPayload({
12271243
name: 'dataStreamNoEditRetention',
1228-
privileges: { delete_index: true, manage_data_stream_lifecycle: false },
1244+
privileges: {
1245+
delete_index: true,
1246+
manage_data_stream_lifecycle: false,
1247+
read_failure_store: true,
1248+
},
12291249
});
12301250

12311251
const dataStreamNoPermissions = createDataStreamPayload({
12321252
name: 'dataStreamNoPermissions',
1233-
privileges: { delete_index: false, manage_data_stream_lifecycle: false },
1253+
privileges: {
1254+
delete_index: false,
1255+
manage_data_stream_lifecycle: false,
1256+
read_failure_store: false,
1257+
},
12341258
});
12351259

12361260
describe('delete', () => {

x-pack/platform/plugins/shared/index_management/common/types/data_streams.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ type TimestampField = TimestampFieldFromEs;
2323
interface PrivilegesFromEs {
2424
delete_index: boolean;
2525
manage_data_stream_lifecycle: boolean;
26+
read_failure_store: boolean;
2627
}
2728

2829
type Privileges = PrivilegesFromEs;
@@ -46,6 +47,7 @@ export interface EnhancedDataStreamFromEs extends IndicesDataStream {
4647
privileges: {
4748
delete_index: boolean;
4849
manage_data_stream_lifecycle: boolean;
50+
read_failure_store: boolean;
4951
};
5052
index_mode?: string | null;
5153
}
@@ -68,6 +70,7 @@ export interface DataStream {
6870
privileges: Privileges;
6971
hidden: boolean;
7072
nextGenerationManagedBy: string;
73+
failureStoreEnabled?: boolean;
7174
lifecycle?: IndicesDataStreamLifecycleWithRollover & {
7275
enabled?: boolean;
7376
effective_retention?: string;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import React from 'react';
9+
import {
10+
EuiModal,
11+
EuiModalBody,
12+
EuiModalFooter,
13+
EuiModalHeader,
14+
EuiModalHeaderTitle,
15+
EuiButtonEmpty,
16+
EuiButton,
17+
EuiSpacer,
18+
EuiLink,
19+
} from '@elastic/eui';
20+
import { i18n } from '@kbn/i18n';
21+
import { FormattedMessage } from '@kbn/i18n-react';
22+
import { configureFailureStoreFormSchema } from './schema';
23+
import {
24+
useForm,
25+
useFormIsModified,
26+
Form,
27+
UseField,
28+
ToggleField,
29+
} from '../../../../../shared_imports';
30+
31+
import { documentationService } from '../../../../services/documentation';
32+
import { DataStream } from '../../../../../../common';
33+
import { useAppContext } from '../../../../app_context';
34+
import { updateDSFailureStore } from '../../../../services/api';
35+
36+
interface Props {
37+
dataStreams: DataStream[];
38+
ilmPolicyName?: string;
39+
ilmPolicyLink?: string;
40+
onClose: (data?: { hasUpdatedFailureStore: boolean }) => void;
41+
}
42+
43+
export const ConfigureFailureStoreModal: React.FunctionComponent<Props> = ({
44+
dataStreams,
45+
onClose,
46+
}) => {
47+
// We will support multiple data streams in the future, but for now we only support one.
48+
const dataStream = dataStreams[0];
49+
50+
const {
51+
services: { notificationService },
52+
} = useAppContext();
53+
54+
const { form } = useForm({
55+
defaultValue: {
56+
dsFailureStore: dataStream?.failureStoreEnabled ?? false,
57+
},
58+
schema: configureFailureStoreFormSchema,
59+
id: 'configureFailureStoreForm',
60+
});
61+
const isDirty = useFormIsModified({ form });
62+
63+
const formHasErrors = form.getErrors().length > 0;
64+
const disableSubmit = formHasErrors || !isDirty || form.isValid === false;
65+
66+
const onSubmitForm = async () => {
67+
const { isValid, data } = await form.submit();
68+
69+
if (!isValid) {
70+
return;
71+
}
72+
73+
return updateDSFailureStore([dataStream.name], data).then(({ data: responseData, error }) => {
74+
if (responseData) {
75+
if (responseData.warning) {
76+
notificationService.showWarningToast(responseData.warning);
77+
return onClose({ hasUpdatedFailureStore: true });
78+
}
79+
80+
const successMessage = i18n.translate(
81+
'xpack.idxMgmt.dataStreams.configureFailureStoreModal.successFailureStoreNotification',
82+
{
83+
defaultMessage:
84+
'Failure store {disabledFailureStore, plural, one { disabled } other { enabled } }',
85+
values: { disabledFailureStore: !data.dsFailureStore ? 1 : 0 },
86+
}
87+
);
88+
89+
notificationService.showSuccessToast(successMessage);
90+
91+
return onClose({ hasUpdatedFailureStore: true });
92+
}
93+
94+
if (error) {
95+
const errorMessage = i18n.translate(
96+
'xpack.idxMgmt.dataStreams.configureFailureStoreModal.errorFailureStoreNotification',
97+
{
98+
defaultMessage: "Error configuring failure store: ''{error}''",
99+
values: { error: error.message },
100+
}
101+
);
102+
notificationService.showDangerToast(errorMessage);
103+
}
104+
105+
onClose();
106+
});
107+
};
108+
109+
return (
110+
<EuiModal
111+
onClose={() => onClose()}
112+
data-test-subj="configureFailureStoreModal"
113+
css={{ width: 650 }}
114+
>
115+
<Form form={form} data-test-subj="configureFailureStoreForm">
116+
<EuiModalHeader>
117+
<EuiModalHeaderTitle>
118+
<FormattedMessage
119+
id="xpack.idxMgmt.dataStreams.configureFailureStoreModal.modalTitleText"
120+
defaultMessage="Configure failure store"
121+
/>
122+
</EuiModalHeaderTitle>
123+
</EuiModalHeader>
124+
125+
<EuiModalBody>
126+
<FormattedMessage
127+
id="xpack.idxMgmt.dataStreams.configureFailureStoreModal.modalDescriptionText"
128+
defaultMessage="A failure store is a secondary index within a data stream, used to store failed documents. {docLink}."
129+
values={{
130+
docLink: (
131+
<EuiLink
132+
href={documentationService.getDataStreamsFailureStoreLink()}
133+
target="_blank"
134+
external
135+
data-test-subj="failureStoreDocLink"
136+
>
137+
<FormattedMessage
138+
id="xpack.idxMgmt.dataStreams.configureFailureStoreModal.modalDescriptionLinkText"
139+
defaultMessage="Learn more"
140+
/>
141+
</EuiLink>
142+
),
143+
}}
144+
/>
145+
<EuiSpacer />
146+
147+
<UseField
148+
path="dsFailureStore"
149+
component={ToggleField}
150+
data-test-subj="enableDataStreamFailureStoreToggle"
151+
euiFieldProps={{
152+
label: i18n.translate(
153+
'xpack.idxMgmt.dataStreams.configureFailureStoreModal.infiniteRetentionPeriodField',
154+
{
155+
defaultMessage: 'Enable data stream failure store',
156+
}
157+
),
158+
}}
159+
/>
160+
161+
<EuiSpacer />
162+
</EuiModalBody>
163+
164+
<EuiModalFooter>
165+
<EuiButtonEmpty data-test-subj="cancelButton" onClick={() => onClose()}>
166+
<FormattedMessage
167+
id="xpack.idxMgmt.dataStreams.configureFailureStoreModal.cancelButtonLabel"
168+
defaultMessage="Cancel"
169+
/>
170+
</EuiButtonEmpty>
171+
172+
<EuiButton
173+
fill
174+
type="submit"
175+
isLoading={false}
176+
disabled={disableSubmit}
177+
data-test-subj="saveButton"
178+
onClick={onSubmitForm}
179+
>
180+
<FormattedMessage
181+
id="xpack.idxMgmt.dataStreams.configureFailureStoreModal.saveButtonLabel"
182+
defaultMessage="Save"
183+
/>
184+
</EuiButton>
185+
</EuiModalFooter>
186+
</Form>
187+
</EuiModal>
188+
);
189+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
export { ConfigureFailureStoreModal } from './configure_failure_store_modal';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { FIELD_TYPES, FormSchema } from '@kbn/es-ui-shared-plugin/static/forms/hook_form_lib';
9+
10+
export const configureFailureStoreFormSchema: FormSchema = {
11+
dsFailureStore: {
12+
type: FIELD_TYPES.TOGGLE,
13+
defaultValue: false,
14+
},
15+
};

0 commit comments

Comments
 (0)