From d056b2997e8c391b83d04765471670310a203850 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 3 Jun 2020 12:15:52 +0200 Subject: [PATCH 01/43] Sort endpoint responses into indices and datastreams The server endpoint for policies now returns data streams and filters out backing indices from the indices array it returned previously --- .../server/routes/api/policy.ts | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts b/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts index 90667eda23b35..313830eb0fa9c 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts @@ -232,16 +232,44 @@ export function registerPolicyRoutes({ const { callAsCurrentUser } = ctx.snapshotRestore!.client; try { - const indices: Array<{ - index: string; - }> = await callAsCurrentUser('cat.indices', { - format: 'json', - h: 'index', + const indices: { + [indexName: string]: { data_stream?: string }; + } = await callAsCurrentUser('transport.request', { + method: 'GET', + path: `/*`, + query: { + expand_wildcards: 'all,hidden', + }, }); + // TODO: This needs to be revisited once https://github.com/elastic/kibana/issues/64858 is + // because we will have a better endpoint for retrieving index, data stream and alias information. + const indicesAndDataStreams = Object.entries(indices).reduce<{ + indices: string[]; + dataStreams: Record; + }>( + (acc, [name, { data_stream: dataStream }]) => { + if (dataStream) { + return { + ...acc, + dataStreams: { + ...acc.dataStreams, + [dataStream]: undefined, + }, + }; + } + return { + ...acc, + indices: acc.indices.concat(name), + }; + }, + { indices: [], dataStreams: {} } + ); + return res.ok({ body: { - indices: indices.map(({ index }) => index).sort(), + indices: indicesAndDataStreams.indices.sort(), + dataStreams: Object.keys(indicesAndDataStreams.dataStreams).sort(), }, }); } catch (e) { From 4af5a8debe9279065e252599f24848be54797ffe Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 3 Jun 2020 12:54:44 +0200 Subject: [PATCH 02/43] Refactor indices switch and field out of the step settings file --- .../policy_form/steps/step_settings.tsx | 469 ------------------ .../fields/data_streams_field.tsx | 5 + .../steps/step_settings/fields/index.ts | 7 + .../step_settings/fields/indices_field.tsx | 317 ++++++++++++ .../policy_form/steps/step_settings/index.ts | 7 + .../steps/step_settings/step_settings.tsx | 202 ++++++++ 6 files changed, 538 insertions(+), 469 deletions(-) delete mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings.tsx create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/index.ts create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings.tsx deleted file mode 100644 index 07a6272312302..0000000000000 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings.tsx +++ /dev/null @@ -1,469 +0,0 @@ -/* - * 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 React, { Fragment, useState } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { - EuiDescribedFormGroup, - EuiTitle, - EuiFormRow, - EuiFlexGroup, - EuiFlexItem, - EuiButtonEmpty, - EuiSpacer, - EuiSwitch, - EuiLink, - EuiSelectable, - EuiPanel, - EuiComboBox, - EuiToolTip, -} from '@elastic/eui'; -import { EuiSelectableOption } from '@elastic/eui'; -import { SlmPolicyPayload, SnapshotConfig } from '../../../../../common/types'; -import { documentationLinksService } from '../../../services/documentation'; -import { useServices } from '../../../app_context'; -import { StepProps } from './'; - -export const PolicyStepSettings: React.FunctionComponent = ({ - policy, - indices, - updatePolicy, - errors, -}) => { - const { i18n } = useServices(); - const { config = {}, isManagedPolicy } = policy; - - const updatePolicyConfig = (updatedFields: Partial): void => { - const newConfig = { ...config, ...updatedFields }; - updatePolicy({ - config: newConfig, - }); - }; - - // States for choosing all indices, or a subset, including caching previously chosen subset list - const [isAllIndices, setIsAllIndices] = useState(!Boolean(config.indices)); - const [indicesSelection, setIndicesSelection] = useState([...indices]); - const [indicesOptions, setIndicesOptions] = useState( - indices.map( - (index): EuiSelectableOption => ({ - label: index, - checked: - isAllIndices || - // If indices is a string, we default to custom input mode, so we mark individual indices - // as selected if user goes back to list mode - typeof config.indices === 'string' || - (Array.isArray(config.indices) && config.indices.includes(index)) - ? 'on' - : undefined, - }) - ) - ); - - // State for using selectable indices list or custom patterns - // Users with more than 100 indices will probably want to use an index pattern to select - // them instead, so we'll default to showing them the index pattern input. - const [selectIndicesMode, setSelectIndicesMode] = useState<'list' | 'custom'>( - typeof config.indices === 'string' || - (Array.isArray(config.indices) && config.indices.length > 100) - ? 'custom' - : 'list' - ); - - // State for custom patterns - const [indexPatterns, setIndexPatterns] = useState( - typeof config.indices === 'string' ? config.indices.split(',') : [] - ); - - const renderIndicesField = () => { - const indicesSwitch = ( - - } - checked={isAllIndices} - disabled={isManagedPolicy} - data-test-subj="allIndicesToggle" - onChange={(e) => { - const isChecked = e.target.checked; - setIsAllIndices(isChecked); - if (isChecked) { - updatePolicyConfig({ indices: undefined }); - } else { - updatePolicyConfig({ - indices: - selectIndicesMode === 'custom' - ? indexPatterns.join(',') - : [...(indicesSelection || [])], - }); - } - }} - /> - ); - - return ( - -

- -

- - } - description={ - - } - fullWidth - > - - - {isManagedPolicy ? ( - - -

- } - > - {indicesSwitch} -
- ) : ( - indicesSwitch - )} - {isAllIndices ? null : ( - - - - - - - - { - setSelectIndicesMode('custom'); - updatePolicyConfig({ indices: indexPatterns.join(',') }); - }} - > - - - - - ) : ( - - - - - - { - setSelectIndicesMode('list'); - updatePolicyConfig({ indices: indicesSelection }); - }} - > - - - - - ) - } - helpText={ - selectIndicesMode === 'list' ? ( - 0 ? ( - { - // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed - indicesOptions.forEach((option: EuiSelectableOption) => { - option.checked = undefined; - }); - updatePolicyConfig({ indices: [] }); - setIndicesSelection([]); - }} - > - - - ) : ( - { - // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed - indicesOptions.forEach((option: EuiSelectableOption) => { - option.checked = 'on'; - }); - updatePolicyConfig({ indices: [...indices] }); - setIndicesSelection([...indices]); - }} - > - - - ), - }} - /> - ) : null - } - isInvalid={Boolean(errors.indices)} - error={errors.indices} - > - {selectIndicesMode === 'list' ? ( - { - const newSelectedIndices: string[] = []; - options.forEach(({ label, checked }) => { - if (checked === 'on') { - newSelectedIndices.push(label); - } - }); - setIndicesOptions(options); - updatePolicyConfig({ indices: newSelectedIndices }); - setIndicesSelection(newSelectedIndices); - }} - searchable - height={300} - > - {(list, search) => ( - - {search} - {list} - - )} - - ) : ( - ({ label: index }))} - placeholder={i18n.translate( - 'xpack.snapshotRestore.policyForm.stepSettings.indicesPatternPlaceholder', - { - defaultMessage: 'Enter index patterns, i.e. logstash-*', - } - )} - selectedOptions={indexPatterns.map((pattern) => ({ label: pattern }))} - onCreateOption={(pattern: string) => { - if (!pattern.trim().length) { - return; - } - const newPatterns = [...indexPatterns, pattern]; - setIndexPatterns(newPatterns); - updatePolicyConfig({ - indices: newPatterns.join(','), - }); - }} - onChange={(patterns: Array<{ label: string }>) => { - const newPatterns = patterns.map(({ label }) => label); - setIndexPatterns(newPatterns); - updatePolicyConfig({ - indices: newPatterns.join(','), - }); - }} - /> - )} - - - )} -
-
-
- ); - }; - - const renderIgnoreUnavailableField = () => ( - -

- -

- - } - description={ - - } - fullWidth - > - - - } - checked={Boolean(config.ignoreUnavailable)} - onChange={(e) => { - updatePolicyConfig({ - ignoreUnavailable: e.target.checked, - }); - }} - /> - -
- ); - - const renderPartialField = () => ( - -

- -

- - } - description={ - - } - fullWidth - > - - - } - checked={Boolean(config.partial)} - onChange={(e) => { - updatePolicyConfig({ - partial: e.target.checked, - }); - }} - /> - -
- ); - - const renderIncludeGlobalStateField = () => ( - -

- -

- - } - description={ - - } - fullWidth - > - - - } - checked={config.includeGlobalState === undefined || config.includeGlobalState} - onChange={(e) => { - updatePolicyConfig({ - includeGlobalState: e.target.checked, - }); - }} - /> - -
- ); - return ( -
- {/* Step title and doc link */} - - - -

- -

-
-
- - - - - - -
- - - {renderIndicesField()} - {renderIgnoreUnavailableField()} - {renderPartialField()} - {renderIncludeGlobalStateField()} -
- ); -}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx new file mode 100644 index 0000000000000..41bc2aa258807 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx @@ -0,0 +1,5 @@ +/* + * 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. + */ diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts new file mode 100644 index 0000000000000..f5c429cb65bbb --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { IndicesField } from './indices_field'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx new file mode 100644 index 0000000000000..debc876c71712 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx @@ -0,0 +1,317 @@ +/* + * 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 React, { Fragment, FunctionComponent, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { + EuiComboBox, + EuiDescribedFormGroup, + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiLink, + EuiPanel, + EuiSelectable, + EuiSelectableOption, + EuiSpacer, + EuiSwitch, + EuiTitle, + EuiToolTip, +} from '@elastic/eui'; + +import { SnapshotConfig } from '../../../../../../../common/types'; +import { useServices } from '../../../../../app_context'; +import { PolicyValidation } from '../../../../../services/validation'; + +interface Props { + isManagedPolicy: boolean; + indices?: string[] | string; + onUpdate: (arg: { indices?: string[] | string }) => void; + errors: PolicyValidation['errors']; +} + +const getIndicesArray = (indices?: string[] | string): string[] => + indices && Array.isArray(indices) + ? indices + : typeof indices === 'string' + ? indices.split(',') + : []; + +export const IndicesField: FunctionComponent = ({ + isManagedPolicy, + indices, + onUpdate, + errors, +}) => { + const { i18n } = useServices(); + const [isAllIndices, setIsAllIndices] = useState(!Boolean(indices)); + const [indicesSelection, setIndicesSelection] = useState([ + ...getIndicesArray(indices), + ]); + + // States for choosing all indices, or a subset, including caching previously chosen subset list + const [indicesOptions, setIndicesOptions] = useState(() => { + return getIndicesArray(indices).map( + (index): EuiSelectableOption => ({ + label: index, + checked: + isAllIndices || + // If indices is a string, we default to custom input mode, so we mark individual indices + // as selected if user goes back to list mode + typeof indices === 'string' || + (Array.isArray(indices) && indices.includes(index)) + ? 'on' + : undefined, + }) + ); + }); + + // State for using selectable indices list or custom patterns + // Users with more than 100 indices will probably want to use an index pattern to select + // them instead, so we'll default to showing them the index pattern input. + const [selectIndicesMode, setSelectIndicesMode] = useState<'list' | 'custom'>( + typeof indices === 'string' || (Array.isArray(indices) && indices.length > 100) + ? 'custom' + : 'list' + ); + + // State for custom patterns + const [indexPatterns, setIndexPatterns] = useState( + typeof indices === 'string' ? (indices as string).split(',') : [] + ); + + const indicesSwitch = ( + + } + checked={isAllIndices} + disabled={isManagedPolicy} + data-test-subj="allIndicesToggle" + onChange={(e) => { + const isChecked = e.target.checked; + setIsAllIndices(isChecked); + if (isChecked) { + onUpdate({ indices: undefined }); + } else { + onUpdate({ + indices: + selectIndicesMode === 'custom' + ? indexPatterns.join(',') + : [...(indicesSelection || [])], + }); + } + }} + /> + ); + + return ( + +

+ +

+ + } + description={ + + } + fullWidth + > + + + {isManagedPolicy ? ( + + +

+ } + > + {indicesSwitch} +
+ ) : ( + indicesSwitch + )} + {isAllIndices ? null : ( + + + + + + + + { + setSelectIndicesMode('custom'); + onUpdate({ indices: indexPatterns.join(',') }); + }} + > + + + + + ) : ( + + + + + + { + setSelectIndicesMode('list'); + onUpdate({ indices: indicesSelection }); + }} + > + + + + + ) + } + helpText={ + selectIndicesMode === 'list' ? ( + 0 ? ( + { + // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed + indicesOptions.forEach((option: EuiSelectableOption) => { + option.checked = undefined; + }); + onUpdate({ indices: [] }); + setIndicesSelection([]); + }} + > + + + ) : ( + { + // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed + indicesOptions.forEach((option: EuiSelectableOption) => { + option.checked = 'on'; + }); + onUpdate({ indices: [...getIndicesArray(indices)] }); + setIndicesSelection([...getIndicesArray(indices)]); + }} + > + + + ), + }} + /> + ) : null + } + isInvalid={Boolean(errors.indices)} + error={errors.indices} + > + {selectIndicesMode === 'list' ? ( + { + const newSelectedIndices: string[] = []; + options.forEach(({ label, checked }) => { + if (checked === 'on') { + newSelectedIndices.push(label); + } + }); + setIndicesOptions(options); + onUpdate({ indices: newSelectedIndices }); + setIndicesSelection(newSelectedIndices); + }} + searchable + height={300} + > + {(list, search) => ( + + {search} + {list} + + )} + + ) : ( + ({ label: index }))} + placeholder={i18n.translate( + 'xpack.snapshotRestore.policyForm.stepSettings.indicesPatternPlaceholder', + { + defaultMessage: 'Enter index patterns, i.e. logstash-*', + } + )} + selectedOptions={indexPatterns.map((pattern) => ({ label: pattern }))} + onCreateOption={(pattern: string) => { + if (!pattern.trim().length) { + return; + } + const newPatterns = [...indexPatterns, pattern]; + setIndexPatterns(newPatterns); + onUpdate({ + indices: newPatterns.join(','), + }); + }} + onChange={(patterns: Array<{ label: string }>) => { + const newPatterns = patterns.map(({ label }) => label); + setIndexPatterns(newPatterns); + onUpdate({ + indices: newPatterns.join(','), + }); + }} + /> + )} + + + )} +
+
+
+ ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/index.ts new file mode 100644 index 0000000000000..24e9b36e74889 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { PolicyStepSettings } from './step_settings'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx new file mode 100644 index 0000000000000..2897f617c6ce5 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx @@ -0,0 +1,202 @@ +/* + * 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 React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiDescribedFormGroup, + EuiTitle, + EuiFormRow, + EuiFlexGroup, + EuiFlexItem, + EuiButtonEmpty, + EuiSpacer, + EuiSwitch, +} from '@elastic/eui'; + +import { SlmPolicyPayload } from '../../../../../../common/types'; +import { documentationLinksService } from '../../../../services/documentation'; +import { StepProps } from '../'; + +import { IndicesField } from './fields'; + +export const PolicyStepSettings: React.FunctionComponent = ({ + policy, + indices, + updatePolicy, + errors, +}) => { + const { config = {}, isManagedPolicy } = policy; + + const updatePolicyConfig = (updatedFields: Partial): void => { + const newConfig = { ...config, ...updatedFields }; + updatePolicy({ + config: newConfig, + }); + }; + + const renderIgnoreUnavailableField = () => ( + +

+ +

+ + } + description={ + + } + fullWidth + > + + + } + checked={Boolean(config.ignoreUnavailable)} + onChange={(e) => { + updatePolicyConfig({ + ignoreUnavailable: e.target.checked, + }); + }} + /> + +
+ ); + + const renderPartialField = () => ( + +

+ +

+ + } + description={ + + } + fullWidth + > + + + } + checked={Boolean(config.partial)} + onChange={(e) => { + updatePolicyConfig({ + partial: e.target.checked, + }); + }} + /> + +
+ ); + + const renderIncludeGlobalStateField = () => ( + +

+ +

+ + } + description={ + + } + fullWidth + > + + + } + checked={config.includeGlobalState === undefined || config.includeGlobalState} + onChange={(e) => { + updatePolicyConfig({ + includeGlobalState: e.target.checked, + }); + }} + /> + +
+ ); + return ( +
+ {/* Step title and doc link */} + + + +

+ +

+
+
+ + + + + + +
+ + + + {renderIgnoreUnavailableField()} + {renderPartialField()} + {renderIncludeGlobalStateField()} +
+ ); +}; From 8861ec2125d765aff8c1c621fdacbe569bb339e0 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 3 Jun 2020 14:15:04 +0200 Subject: [PATCH 03/43] Fix indices field form behaviour --- .../step_settings/fields/indices_field.tsx | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx index debc876c71712..fb9219b2dcb13 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx @@ -23,47 +23,41 @@ import { EuiToolTip, } from '@elastic/eui'; -import { SnapshotConfig } from '../../../../../../../common/types'; +import { SlmPolicyPayload, SnapshotConfig } from '../../../../../../../common/types'; import { useServices } from '../../../../../app_context'; import { PolicyValidation } from '../../../../../services/validation'; interface Props { isManagedPolicy: boolean; - indices?: string[] | string; + policy: SlmPolicyPayload; + indices: string[]; onUpdate: (arg: { indices?: string[] | string }) => void; errors: PolicyValidation['errors']; } -const getIndicesArray = (indices?: string[] | string): string[] => - indices && Array.isArray(indices) - ? indices - : typeof indices === 'string' - ? indices.split(',') - : []; - export const IndicesField: FunctionComponent = ({ isManagedPolicy, indices, + policy, onUpdate, errors, }) => { const { i18n } = useServices(); - const [isAllIndices, setIsAllIndices] = useState(!Boolean(indices)); - const [indicesSelection, setIndicesSelection] = useState([ - ...getIndicesArray(indices), - ]); + const { config = {} } = policy; + const [isAllIndices, setIsAllIndices] = useState(!Boolean(config.indices)); + const [indicesSelection, setIndicesSelection] = useState([...indices]); // States for choosing all indices, or a subset, including caching previously chosen subset list const [indicesOptions, setIndicesOptions] = useState(() => { - return getIndicesArray(indices).map( + return indices.map( (index): EuiSelectableOption => ({ label: index, checked: isAllIndices || // If indices is a string, we default to custom input mode, so we mark individual indices // as selected if user goes back to list mode - typeof indices === 'string' || - (Array.isArray(indices) && indices.includes(index)) + typeof config.indices === 'string' || + (Array.isArray(config.indices) && config.indices.includes(index)) ? 'on' : undefined, }) @@ -74,14 +68,15 @@ export const IndicesField: FunctionComponent = ({ // Users with more than 100 indices will probably want to use an index pattern to select // them instead, so we'll default to showing them the index pattern input. const [selectIndicesMode, setSelectIndicesMode] = useState<'list' | 'custom'>( - typeof indices === 'string' || (Array.isArray(indices) && indices.length > 100) + typeof config.indices === 'string' || + (Array.isArray(config.indices) && config.indices.length > 100) ? 'custom' : 'list' ); // State for custom patterns const [indexPatterns, setIndexPatterns] = useState( - typeof indices === 'string' ? (indices as string).split(',') : [] + typeof config.indices === 'string' ? (config.indices as string).split(',') : [] ); const indicesSwitch = ( @@ -210,9 +205,9 @@ export const IndicesField: FunctionComponent = ({ id="xpack.snapshotRestore.policyForm.stepSettings.selectIndicesHelpText" defaultMessage="{count} {count, plural, one {index} other {indices}} will be backed up. {selectOrDeselectAllLink}" values={{ - count: indices && indices.length, + count: config.indices && config.indices.length, selectOrDeselectAllLink: - indices && indices.length > 0 ? ( + config.indices && config.indices.length > 0 ? ( { @@ -236,8 +231,8 @@ export const IndicesField: FunctionComponent = ({ indicesOptions.forEach((option: EuiSelectableOption) => { option.checked = 'on'; }); - onUpdate({ indices: [...getIndicesArray(indices)] }); - setIndicesSelection([...getIndicesArray(indices)]); + onUpdate({ indices: [...indices] }); + setIndicesSelection([...indices]); }} > = ({ ) : ( ({ label: index }))} + options={indices.map((index) => ({ label: index }))} placeholder={i18n.translate( 'xpack.snapshotRestore.policyForm.stepSettings.indicesPatternPlaceholder', { From f219f481c87c1c112bb701a7de8843f25cc08942 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 3 Jun 2020 15:08:44 +0200 Subject: [PATCH 04/43] WiP on UI. Added the second table per mockup for add and edit. --- .../snapshot_restore/common/lib/index.ts | 1 + .../common/lib/snapshot_serialization.ts | 16 +- .../snapshot_restore/common/lib/utils.ts | 13 + .../snapshot_restore/common/types/snapshot.ts | 1 + .../components/policy_form/policy_form.tsx | 5 +- .../components/policy_form/steps/index.ts | 1 + .../fields/data_streams_field.tsx | 241 ++++++++++++++++++ .../steps/step_settings/fields/index.ts | 1 + .../steps/step_settings/step_settings.tsx | 15 +- .../sections/policy_add/policy_add.tsx | 4 +- .../sections/policy_edit/policy_edit.tsx | 4 +- 11 files changed, 295 insertions(+), 7 deletions(-) create mode 100644 x-pack/plugins/snapshot_restore/common/lib/utils.ts diff --git a/x-pack/plugins/snapshot_restore/common/lib/index.ts b/x-pack/plugins/snapshot_restore/common/lib/index.ts index 579dae0265939..363be2a2de7a7 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/index.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/index.ts @@ -16,3 +16,4 @@ export { serializeSnapshotRetention, } from './snapshot_serialization'; export { deserializePolicy, serializePolicy } from './policy_serialization'; +export { indicesToArray } from './utils'; diff --git a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts index a636cc1f6326e..a15369e19695b 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts @@ -17,6 +17,8 @@ import { import { deserializeTime, serializeTime } from './time_serialization'; +import { indicesToArray } from './utils'; + export function deserializeSnapshotDetails( repository: string, snapshotDetailsEs: SnapshotDetailsEs, @@ -125,10 +127,20 @@ export function deserializeSnapshotConfig(snapshotConfigEs: SnapshotConfigEs): S } export function serializeSnapshotConfig(snapshotConfig: SnapshotConfig): SnapshotConfigEs { - const { indices, ignoreUnavailable, includeGlobalState, partial, metadata } = snapshotConfig; + const { + indices, + dataStreams, + ignoreUnavailable, + includeGlobalState, + partial, + metadata, + } = snapshotConfig; + + const indicesArray = indicesToArray(indices); + const dataStreamsArray = indicesToArray(dataStreams).map((d) => `${d}-*`); const snapshotConfigEs: SnapshotConfigEs = { - indices, + indices: indicesArray.concat(dataStreamsArray), ignore_unavailable: ignoreUnavailable, include_global_state: includeGlobalState, partial, diff --git a/x-pack/plugins/snapshot_restore/common/lib/utils.ts b/x-pack/plugins/snapshot_restore/common/lib/utils.ts new file mode 100644 index 0000000000000..fb35f59f8b973 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/common/lib/utils.ts @@ -0,0 +1,13 @@ +/* + * 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. + */ + +export const indicesToArray = (indices?: string | string[]): string[] => { + return indices && Array.isArray(indices) + ? indices + : typeof indices === 'string' + ? indices.split(',') + : []; +}; diff --git a/x-pack/plugins/snapshot_restore/common/types/snapshot.ts b/x-pack/plugins/snapshot_restore/common/types/snapshot.ts index a46f5c7921bfe..e81eb3c2a92dc 100644 --- a/x-pack/plugins/snapshot_restore/common/types/snapshot.ts +++ b/x-pack/plugins/snapshot_restore/common/types/snapshot.ts @@ -5,6 +5,7 @@ */ export interface SnapshotConfig { indices?: string | string[]; + dataStreams?: string | string[]; ignoreUnavailable?: boolean; includeGlobalState?: boolean; partial?: boolean; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx index f9cad7cc4e070..3fdb3a098a04c 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx @@ -28,6 +28,7 @@ import { PolicyNavigation } from './navigation'; interface Props { policy: SlmPolicyPayload; indices: string[]; + dataStreams: string[]; currentUrl: string; isEditing?: boolean; isSaving: boolean; @@ -40,6 +41,7 @@ interface Props { export const PolicyForm: React.FunctionComponent = ({ policy: originalPolicy, indices, + dataStreams, currentUrl, isEditing, isSaving, @@ -132,6 +134,7 @@ export const PolicyForm: React.FunctionComponent = ({ = ({ {currentStep === lastStep ? ( savePolicy()} diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/index.ts index 8b251de80a8e1..a79a6ecb42e45 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/index.ts @@ -10,6 +10,7 @@ import { PolicyValidation } from '../../../services/validation'; export interface StepProps { policy: SlmPolicyPayload; indices: string[]; + dataStreams: string[]; updatePolicy: (updatedSettings: Partial, validationHelperData?: any) => void; isEditing: boolean; currentUrl: string; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx index 41bc2aa258807..ae81bba39384e 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx @@ -3,3 +3,244 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + +import React, { Fragment, FunctionComponent, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { + EuiDescribedFormGroup, + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiLink, + EuiPanel, + EuiSelectable, + EuiSelectableOption, + EuiSpacer, + EuiSwitch, + EuiTitle, + EuiToolTip, +} from '@elastic/eui'; + +import { SlmPolicyPayload, SnapshotConfig } from '../../../../../../../common/types'; +import { PolicyValidation } from '../../../../../services/validation'; +import { indicesToArray } from '../../../../../../../common/lib'; + +interface Props { + isManagedPolicy: boolean; + policy: SlmPolicyPayload; + dataStreams: string[]; + onUpdate: (arg: { dataStreams?: string[] | string }) => void; + errors: PolicyValidation['errors']; +} + +const hasSelectedSubsetOfDataStreams = (dataStreams: string[], selectedDataStreams: string[]) => { + return selectedDataStreams.length && dataStreams.length > selectedDataStreams.length; +}; + +const getArrayOfSelectedDataStreams = ( + dataStreams: string[], + indices?: string[] | string +): string[] => { + const arrayOfIndices = indicesToArray(indices); + return dataStreams.filter((d) => { + return arrayOfIndices.some((i) => i.startsWith(d)); + }); +}; + +export const DataStreamsField: FunctionComponent = ({ + isManagedPolicy, + dataStreams, + policy, + onUpdate, + errors, +}) => { + const arrayOfSelectedDataStreams = getArrayOfSelectedDataStreams( + dataStreams, + policy.config?.indices + ); + const { config = {} } = policy; + const [isAllDataStreams, setIsAllDataStreams] = useState( + () => !hasSelectedSubsetOfDataStreams(dataStreams, arrayOfSelectedDataStreams) + ); + const [dataStreamsSelection, setDataStreamsSelection] = useState([ + ...dataStreams, + ]); + + // States for choosing all data streams, or a subset, including caching previously chosen subset list + const [dataStreamOptions, setDataStreamOptions] = useState(() => { + return dataStreams.map( + (dataStream): EuiSelectableOption => ({ + label: dataStream, + checked: + isAllDataStreams || + // If indices is a string, we default to custom input mode, so we mark individual data streams + // as selected if user goes back to list mode + typeof config.indices === 'string' || + arrayOfSelectedDataStreams.includes(dataStream) + ? 'on' + : undefined, + }) + ); + }); + + const dataStreamsSwitch = ( + + } + checked={isAllDataStreams} + disabled={isManagedPolicy} + data-test-subj="allIndicesToggle" + onChange={(e) => { + const isChecked = e.target.checked; + setIsAllDataStreams(isChecked); + if (isChecked) { + onUpdate({ dataStreams: undefined }); + } else { + onUpdate({ + dataStreams: [...(dataStreamsSelection || [])], + }); + } + }} + /> + ); + + return ( + +

+ +

+ + } + description={ + + } + fullWidth + > + + + {isManagedPolicy ? ( + + +

+ } + > + {dataStreamsSwitch} +
+ ) : ( + dataStreamsSwitch + )} + {isAllDataStreams ? null : ( + + + + + + + + } + helpText={ + 0 ? ( + { + // TODO: Change this to setDataStreamOptions() when https://github.com/elastic/eui/issues/2071 is fixed + dataStreamOptions.forEach((option: EuiSelectableOption) => { + option.checked = undefined; + }); + onUpdate({ dataStreams: [] }); + setDataStreamsSelection([]); + }} + > + + + ) : ( + { + // TODO: Change this to setDataStreamOptions() when https://github.com/elastic/eui/issues/2071 is fixed + dataStreamOptions.forEach((option: EuiSelectableOption) => { + option.checked = 'on'; + }); + onUpdate({ dataStreams: [...dataStreams] }); + setDataStreamsSelection([...dataStreams]); + }} + > + + + ), + }} + /> + } + isInvalid={Boolean(errors.indices)} + error={errors.indices} + > + { + { + const newSelectedDataStreams: string[] = []; + options.forEach(({ label, checked }) => { + if (checked === 'on') { + newSelectedDataStreams.push(label); + } + }); + setDataStreamOptions(options); + onUpdate({ dataStreams: newSelectedDataStreams }); + setDataStreamsSelection(newSelectedDataStreams); + }} + searchable + height={300} + > + {(list, search) => ( + + {search} + {list} + + )} + + } + + + )} +
+
+
+ ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts index f5c429cb65bbb..644b8be7818bf 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts @@ -5,3 +5,4 @@ */ export { IndicesField } from './indices_field'; +export { DataStreamsField } from './data_streams_field'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx index 2897f617c6ce5..ede4f79f4d910 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx @@ -20,11 +20,12 @@ import { SlmPolicyPayload } from '../../../../../../common/types'; import { documentationLinksService } from '../../../../services/documentation'; import { StepProps } from '../'; -import { IndicesField } from './fields'; +import { IndicesField, DataStreamsField } from './fields'; export const PolicyStepSettings: React.FunctionComponent = ({ policy, indices, + dataStreams, updatePolicy, errors, }) => { @@ -191,9 +192,19 @@ export const PolicyStepSettings: React.FunctionComponent = ({ + + + {renderIgnoreUnavailableField()} {renderPartialField()} {renderIncludeGlobalStateField()} diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/policy_add/policy_add.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/policy_add/policy_add.tsx index 6d1a432be7f9f..777abb1198a36 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/policy_add/policy_add.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/policy_add/policy_add.tsx @@ -28,8 +28,9 @@ export const PolicyAdd: React.FunctionComponent = ({ const { error: errorLoadingIndices, isLoading: isLoadingIndices, - data: { indices } = { + data: { indices, dataStreams } = { indices: [], + dataStreams: [], }, } = useLoadIndices(); @@ -123,6 +124,7 @@ export const PolicyAdd: React.FunctionComponent = ({ Date: Tue, 23 Jun 2020 13:28:53 +0200 Subject: [PATCH 05/43] add support for creating a policy that backs up data streams end to end --- .../common/lib/snapshot_serialization.ts | 2 +- .../collapsible_data_streams_list.tsx | 77 +++++++++++++++++++ .../collapsible_indices_list.tsx | 0 .../components/collapsible_lists/index.ts | 8 ++ .../public/application/components/index.ts | 2 +- .../policy_form/steps/step_review.tsx | 18 ++++- .../fields/data_streams_field.tsx | 41 +++------- .../steps/step_review.tsx | 2 +- .../server/routes/api/policy.ts | 54 +++++-------- .../server/routes/api/validate_schemas.ts | 1 + .../plugins/snapshot_restore/server/types.ts | 16 ++++ 11 files changed, 150 insertions(+), 71 deletions(-) create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx rename x-pack/plugins/snapshot_restore/public/application/components/{ => collapsible_lists}/collapsible_indices_list.tsx (100%) create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/index.ts diff --git a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts index a15369e19695b..fd87991ee153a 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts @@ -137,7 +137,7 @@ export function serializeSnapshotConfig(snapshotConfig: SnapshotConfig): Snapsho } = snapshotConfig; const indicesArray = indicesToArray(indices); - const dataStreamsArray = indicesToArray(dataStreams).map((d) => `${d}-*`); + const dataStreamsArray = indicesToArray(dataStreams); const snapshotConfigEs: SnapshotConfigEs = { indices: indicesArray.concat(dataStreamsArray), diff --git a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx new file mode 100644 index 0000000000000..0e63714b11b7c --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx @@ -0,0 +1,77 @@ +/* + * 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 React, { useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiTitle, EuiLink, EuiIcon, EuiText, EuiSpacer } from '@elastic/eui'; +interface Props { + dataStreams: string[] | string | undefined; +} + +export const CollapsibleDataStreamsList: React.FunctionComponent = ({ dataStreams }) => { + const [isShowingFullDataStreamsList, setIsShowingFullDataStreamsList] = useState(false); + const displayDataStreams = dataStreams + ? typeof dataStreams === 'string' + ? dataStreams.split(',') + : dataStreams + : undefined; + const hiddenDataStreamsCount = + displayDataStreams && displayDataStreams.length > 10 ? displayDataStreams.length - 10 : 0; + return ( + <> + {displayDataStreams ? ( + <> + +
    + {(isShowingFullDataStreamsList + ? displayDataStreams + : [...displayDataStreams].splice(0, 10) + ).map((dataStream) => ( +
  • + + {dataStream} + +
  • + ))} +
+
+ {hiddenDataStreamsCount ? ( + <> + + + isShowingFullDataStreamsList + ? setIsShowingFullDataStreamsList(false) + : setIsShowingFullDataStreamsList(true) + } + > + {isShowingFullDataStreamsList ? ( + + ) : ( + + )}{' '} + + + + ) : null} + + ) : ( + + )} + + ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_indices_list.tsx b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_indices_list.tsx similarity index 100% rename from x-pack/plugins/snapshot_restore/public/application/components/collapsible_indices_list.tsx rename to x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_indices_list.tsx diff --git a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/index.ts new file mode 100644 index 0000000000000..d58edc983c541 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export { CollapsibleIndicesList } from './collapsible_indices_list'; +export { CollapsibleDataStreamsList } from './collapsible_data_streams_list'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/index.ts index f5bb892389870..91266aae66e27 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/index.ts @@ -15,7 +15,7 @@ export { SnapshotDeleteProvider } from './snapshot_delete_provider'; export { RestoreSnapshotForm } from './restore_snapshot_form'; export { PolicyExecuteProvider } from './policy_execute_provider'; export { PolicyDeleteProvider } from './policy_delete_provider'; -export { CollapsibleIndicesList } from './collapsible_indices_list'; +export { CollapsibleIndicesList, CollapsibleDataStreamsList } from './collapsible_lists'; export { RetentionSettingsUpdateModalProvider, UpdateRetentionSettings, diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx index b2422be3b78c3..216fefab911e5 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx @@ -22,7 +22,7 @@ import { import { serializePolicy } from '../../../../../common/lib'; import { useServices } from '../../../app_context'; import { StepProps } from './'; -import { CollapsibleIndicesList } from '../../collapsible_indices_list'; +import { CollapsibleIndicesList, CollapsibleDataStreamsList } from '../../collapsible_lists'; export const PolicyStepReview: React.FunctionComponent = ({ policy, @@ -30,8 +30,9 @@ export const PolicyStepReview: React.FunctionComponent = ({ }) => { const { i18n } = useServices(); const { name, snapshotName, schedule, repository, config, retention } = policy; - const { indices, includeGlobalState, ignoreUnavailable, partial } = config || { + const { indices, includeGlobalState, ignoreUnavailable, partial, dataStreams } = config || { indices: undefined, + dataStreams: undefined, includeGlobalState: undefined, ignoreUnavailable: undefined, partial: undefined, @@ -157,6 +158,19 @@ export const PolicyStepReview: React.FunctionComponent = ({
+ + + + + + + + + + diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx index ae81bba39384e..920c0739378d6 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx @@ -24,7 +24,6 @@ import { import { SlmPolicyPayload, SnapshotConfig } from '../../../../../../../common/types'; import { PolicyValidation } from '../../../../../services/validation'; -import { indicesToArray } from '../../../../../../../common/lib'; interface Props { isManagedPolicy: boolean; @@ -34,20 +33,6 @@ interface Props { errors: PolicyValidation['errors']; } -const hasSelectedSubsetOfDataStreams = (dataStreams: string[], selectedDataStreams: string[]) => { - return selectedDataStreams.length && dataStreams.length > selectedDataStreams.length; -}; - -const getArrayOfSelectedDataStreams = ( - dataStreams: string[], - indices?: string[] | string -): string[] => { - const arrayOfIndices = indicesToArray(indices); - return dataStreams.filter((d) => { - return arrayOfIndices.some((i) => i.startsWith(d)); - }); -}; - export const DataStreamsField: FunctionComponent = ({ isManagedPolicy, dataStreams, @@ -55,15 +40,9 @@ export const DataStreamsField: FunctionComponent = ({ onUpdate, errors, }) => { - const arrayOfSelectedDataStreams = getArrayOfSelectedDataStreams( - dataStreams, - policy.config?.indices - ); const { config = {} } = policy; - const [isAllDataStreams, setIsAllDataStreams] = useState( - () => !hasSelectedSubsetOfDataStreams(dataStreams, arrayOfSelectedDataStreams) - ); - const [dataStreamsSelection, setDataStreamsSelection] = useState([ + const [isAllDataStreams, setIsAllDataStreams] = useState(() => !config.dataStreams); + const [dataStreamsSelection, setDataStreamsSelection] = useState([ ...dataStreams, ]); @@ -74,10 +53,10 @@ export const DataStreamsField: FunctionComponent = ({ label: dataStream, checked: isAllDataStreams || - // If indices is a string, we default to custom input mode, so we mark individual data streams + // If dataStreams is a string, we default to custom input mode, so we mark individual data streams // as selected if user goes back to list mode - typeof config.indices === 'string' || - arrayOfSelectedDataStreams.includes(dataStream) + typeof config.dataStreams === 'string' || + (Array.isArray(config.dataStreams) && config.dataStreams.includes(dataStream)) ? 'on' : undefined, }) @@ -94,7 +73,7 @@ export const DataStreamsField: FunctionComponent = ({ } checked={isAllDataStreams} disabled={isManagedPolicy} - data-test-subj="allIndicesToggle" + data-test-subj="allDataStreamsToggle" onChange={(e) => { const isChecked = e.target.checked; setIsAllDataStreams(isChecked); @@ -168,9 +147,9 @@ export const DataStreamsField: FunctionComponent = ({ id="xpack.snapshotRestore.policyForm.stepSettings.selectDataStreamsHelpText" defaultMessage="{count} {count, plural, one {data stream} other {data streams}} will be backed up. {selectOrDeselectAllLink}" values={{ - count: arrayOfSelectedDataStreams.length, + count: config.dataStreams?.length, selectOrDeselectAllLink: - arrayOfSelectedDataStreams.length > 0 ? ( + config.dataStreams && config.dataStreams.length > 0 ? ( { @@ -207,8 +186,8 @@ export const DataStreamsField: FunctionComponent = ({ }} /> } - isInvalid={Boolean(errors.indices)} - error={errors.indices} + isInvalid={Boolean(errors.dataStreams)} + error={errors.dataStreams} > { = ({ restoreSettings, diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts b/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts index 313830eb0fa9c..b23a03b474099 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts @@ -8,7 +8,7 @@ import { schema, TypeOf } from '@kbn/config-schema'; import { SlmPolicyEs } from '../../../common/types'; import { deserializePolicy, serializePolicy } from '../../../common/lib'; import { getManagedPolicyNames } from '../../lib'; -import { RouteDependencies } from '../../types'; +import { RouteDependencies, ResolveIndexResponseFromES } from '../../types'; import { addBasePath } from '../helpers'; import { nameParameterSchema, policySchema } from './validate_schemas'; @@ -232,44 +232,28 @@ export function registerPolicyRoutes({ const { callAsCurrentUser } = ctx.snapshotRestore!.client; try { - const indices: { - [indexName: string]: { data_stream?: string }; - } = await callAsCurrentUser('transport.request', { - method: 'GET', - path: `/*`, - query: { - expand_wildcards: 'all,hidden', - }, - }); - - // TODO: This needs to be revisited once https://github.com/elastic/kibana/issues/64858 is - // because we will have a better endpoint for retrieving index, data stream and alias information. - const indicesAndDataStreams = Object.entries(indices).reduce<{ - indices: string[]; - dataStreams: Record; - }>( - (acc, [name, { data_stream: dataStream }]) => { - if (dataStream) { - return { - ...acc, - dataStreams: { - ...acc.dataStreams, - [dataStream]: undefined, - }, - }; - } - return { - ...acc, - indices: acc.indices.concat(name), - }; - }, - { indices: [], dataStreams: {} } + const resolvedIndicesResponse: ResolveIndexResponseFromES = await callAsCurrentUser( + 'transport.request', + { + method: 'GET', + path: `_resolve/index/*`, + query: { + expand_wildcards: 'all,hidden', + }, + } ); return res.ok({ body: { - indices: indicesAndDataStreams.indices.sort(), - dataStreams: Object.keys(indicesAndDataStreams.dataStreams).sort(), + indices: resolvedIndicesResponse.indices + .flatMap((index) => { + if (index.data_stream) { + return []; + } + return index.name; + }) + .sort(), + dataStreams: resolvedIndicesResponse.data_streams.map(({ name }) => name).sort(), }, }); } catch (e) { diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts b/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts index e5df0ec33db0b..0ce3de6a6e061 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts @@ -11,6 +11,7 @@ export const nameParameterSchema = schema.object({ const snapshotConfigSchema = schema.object({ indices: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), + dataStreams: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), ignoreUnavailable: schema.maybe(schema.boolean()), includeGlobalState: schema.maybe(schema.boolean()), partial: schema.maybe(schema.boolean()), diff --git a/x-pack/plugins/snapshot_restore/server/types.ts b/x-pack/plugins/snapshot_restore/server/types.ts index 9710f812abf23..2d71b34289f75 100644 --- a/x-pack/plugins/snapshot_restore/server/types.ts +++ b/x-pack/plugins/snapshot_restore/server/types.ts @@ -31,4 +31,20 @@ export interface RouteDependencies { }; } +/** + * An object representing a resolved index, data stream or alias + */ +interface DataObjectFromES { + name: string; + // per https://github.com/elastic/elasticsearch/pull/57626 + attributes: Array<'open' | 'closed' | 'hidden' | 'frozen'>; + data_stream?: string; +} + +export interface ResolveIndexResponseFromES { + indices: DataObjectFromES[]; + aliases: DataObjectFromES[]; + data_streams: Array>; +} + export type CallAsCurrentUser = ScopedClusterClient['callAsCurrentUser']; From 8db5cd5bae50aa40b499ed512c6172e314beeef8 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 23 Jun 2020 14:14:40 +0200 Subject: [PATCH 06/43] wip on restore flow - added data streams to server response --- .../snapshot_restore/common/lib/snapshot_serialization.test.ts | 1 + .../snapshot_restore/common/lib/snapshot_serialization.ts | 2 ++ x-pack/plugins/snapshot_restore/common/types/snapshot.ts | 2 ++ 3 files changed, 5 insertions(+) diff --git a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.test.ts b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.test.ts index 298fc235fd9cc..473a3392deb3e 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.test.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.test.ts @@ -97,6 +97,7 @@ describe('deserializeSnapshotDetails', () => { version: 'version', // Indices are sorted. indices: ['index1', 'index2', 'index3'], + dataStreams: [], includeGlobalState: false, // Failures are grouped and sorted by index, and the failures themselves are sorted by shard. indexFailures: [ diff --git a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts index fd87991ee153a..33efdc8bc9550 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts @@ -35,6 +35,7 @@ export function deserializeSnapshotDetails( version_id: versionId, version, indices = [], + data_streams: dataStreams = [], include_global_state: includeGlobalState, state, start_time: startTime, @@ -79,6 +80,7 @@ export function deserializeSnapshotDetails( versionId, version, indices: [...indices].sort(), + dataStreams: [...dataStreams].sort(), includeGlobalState, state, startTime, diff --git a/x-pack/plugins/snapshot_restore/common/types/snapshot.ts b/x-pack/plugins/snapshot_restore/common/types/snapshot.ts index e81eb3c2a92dc..c6a58c713388d 100644 --- a/x-pack/plugins/snapshot_restore/common/types/snapshot.ts +++ b/x-pack/plugins/snapshot_restore/common/types/snapshot.ts @@ -31,6 +31,7 @@ export interface SnapshotDetails { versionId: number; version: string; indices: string[]; + dataStreams: string[]; includeGlobalState: boolean; state: string; /** e.g. '2019-04-05T21:56:40.438Z' */ @@ -53,6 +54,7 @@ export interface SnapshotDetailsEs { version_id: number; version: string; indices: string[]; + data_streams?: string[]; include_global_state: boolean; state: string; /** e.g. '2019-04-05T21:56:40.438Z' */ From 86ea659d3a5100d6d6d735d75234305a63167076 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 24 Jun 2020 11:51:31 +0200 Subject: [PATCH 07/43] add logic for detecting whether an index is part of a data stream --- .../snapshot_restore/common/lib/index.ts | 1 + .../lib/is_data_stream_backing_index.ts | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 x-pack/plugins/snapshot_restore/common/lib/is_data_stream_backing_index.ts diff --git a/x-pack/plugins/snapshot_restore/common/lib/index.ts b/x-pack/plugins/snapshot_restore/common/lib/index.ts index 363be2a2de7a7..2e7ca8f3e12cd 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/index.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/index.ts @@ -17,3 +17,4 @@ export { } from './snapshot_serialization'; export { deserializePolicy, serializePolicy } from './policy_serialization'; export { indicesToArray } from './utils'; +export { isDataStreamBackingIndex } from './is_data_stream_backing_index'; diff --git a/x-pack/plugins/snapshot_restore/common/lib/is_data_stream_backing_index.ts b/x-pack/plugins/snapshot_restore/common/lib/is_data_stream_backing_index.ts new file mode 100644 index 0000000000000..aea0de1d875e6 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/common/lib/is_data_stream_backing_index.ts @@ -0,0 +1,21 @@ +/* + * 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. + */ + +/** + * @remark + * WARNING! + * + * This is a very hacky way of determining whether an index is a backing index. + * + * We only do this so that we can show users during a snapshot restore workflow + * that an index is part of a data stream. At the moment there is no way for us + * to get this information from the snapshot itself, even though it contains the + * metadata for the data stream that information is fully opaque to us until after + * we have done the snapshot restore. + */ +export const isDataStreamBackingIndex = (indexName: string) => { + return indexName.startsWith('.ds'); +}; From a153c7f723f9f5a7f3b278e540ef3b54a0c75822 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 24 Jun 2020 12:06:26 +0200 Subject: [PATCH 08/43] fix public jest tests --- .../helpers/setup_environment.tsx | 5 +++++ .../client_integration/policy_add.test.ts | 19 ++++++++++++++++++- .../client_integration/policy_edit.test.ts | 5 ++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx index c4f4876b8a1cd..e26a9e79980f6 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx @@ -64,6 +64,11 @@ export const setupEnvironment = () => { }; }; +window.Worker = function Worker() { + this.postMessage = () => {}; + this.terminate = () => {}; +}; + export const WithAppDependencies = (Comp: any) => (props: any) => ( diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts index a8e6e976bb16d..84d6ef592ef65 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts @@ -37,7 +37,10 @@ describe('', () => { describe('on component mount', () => { beforeEach(async () => { httpRequestsMockHelpers.setLoadRepositoriesResponse({ repositories: [repository] }); - httpRequestsMockHelpers.setLoadIndicesResponse({ indices: ['my_index'] }); + httpRequestsMockHelpers.setLoadIndicesResponse({ + indices: ['my_index'], + dataStreams: ['my_data_stream'], + }); testBed = await setup(); await nextTick(); @@ -111,6 +114,20 @@ describe('', () => { expect(form.getErrorsMessages()).toEqual(['You must select at least one index.']); }); + test('should not require any data streams to be included', async () => { + const { find, form, component } = testBed; + + await act(async () => { + form.toggleEuiSwitch('allDataStreamsToggle', false); + await nextTick(); + component.update(); + }); + + // Deselect all indices from list + find('deselectDataStreamLink').simulate('click'); + + expect(form.getErrorsMessages()).toEqual([]); + }); }); describe('retention (step 3)', () => { diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_edit.test.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_edit.test.ts index 297741755e88b..7eec80890ca86 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_edit.test.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_edit.test.ts @@ -35,7 +35,10 @@ describe('', () => { describe('on component mount', () => { beforeEach(async () => { httpRequestsMockHelpers.setGetPolicyResponse({ policy: POLICY_EDIT }); - httpRequestsMockHelpers.setLoadIndicesResponse({ indices: ['my_index'] }); + httpRequestsMockHelpers.setLoadIndicesResponse({ + indices: ['my_index'], + dataStreams: ['my_data_stream'], + }); httpRequestsMockHelpers.setLoadRepositoriesResponse({ repositories: [{ name: POLICY_EDIT.repository }], }); From 848e76f1e2d9d7c00969b89c0ccd5759c3a63eab Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 24 Jun 2020 12:23:30 +0200 Subject: [PATCH 09/43] fix server side jest tests --- .../server/routes/api/policy.test.ts | 38 ++++++++++++++----- .../server/routes/api/snapshots.test.ts | 1 + 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/policy.test.ts b/x-pack/plugins/snapshot_restore/server/routes/api/policy.test.ts index eb29b7bad37e6..17a8ebc9a5da0 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/policy.test.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/policy.test.ts @@ -6,6 +6,7 @@ import { addBasePath } from '../helpers'; import { registerPolicyRoutes } from './policy'; import { RouterMock, routeDependencies, RequestMock } from '../../test/helpers'; +import { ResolveIndexResponseFromES } from '../../types'; describe('[Snapshot and Restore API Routes] Policy', () => { const mockEsPolicy = { @@ -324,27 +325,44 @@ describe('[Snapshot and Restore API Routes] Policy', () => { }; it('should arrify and sort index names returned from ES', async () => { - const mockEsResponse = [ - { - index: 'fooIndex', - }, - { - index: 'barIndex', - }, - ]; + const mockEsResponse: ResolveIndexResponseFromES = { + indices: [ + { + name: 'fooIndex', + attributes: ['open'], + }, + { + name: 'barIndex', + attributes: ['open'], + }, + ], + aliases: [], + data_streams: [ + { + name: 'testDataStream', + backing_indices: '.ds-test-data-stream-000001', + timestamp_field: '@timestamp', + }, + ], + }; router.callAsCurrentUserResponses = [mockEsResponse]; const expectedResponse = { indices: ['barIndex', 'fooIndex'], + dataStreams: ['testDataStream'], }; await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); }); it('should return empty array if no indices returned from ES', async () => { - const mockEsResponse: any[] = []; + const mockEsResponse: ResolveIndexResponseFromES = { + indices: [], + aliases: [], + data_streams: [], + }; router.callAsCurrentUserResponses = [mockEsResponse]; - const expectedResponse = { indices: [] }; + const expectedResponse = { indices: [], dataStreams: [] }; await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); }); diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.test.ts b/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.test.ts index f913299fc3992..bfe7e96493279 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.test.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.test.ts @@ -14,6 +14,7 @@ const defaultSnapshot = { uuid: undefined, versionId: undefined, version: undefined, + dataStreams: [], indices: [], includeGlobalState: undefined, state: undefined, From 45f22e92db6162533a245fc311953eb793b926b5 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 24 Jun 2020 14:09:51 +0200 Subject: [PATCH 10/43] pivot to different solution in UI while we do not have data streams nicely separated --- .../client_integration/policy_add.test.ts | 14 -- .../snapshot_restore/common/types/index.ts | 1 + .../snapshot_restore/common/types/indices.ts | 14 ++ .../collapsible_data_streams_list.tsx | 77 ------ .../components/collapsible_lists/index.ts | 1 - .../public/application/components/index.ts | 2 +- .../components/policy_form/policy_form.tsx | 7 +- .../components/policy_form/steps/index.ts | 5 +- .../policy_form/steps/step_review.tsx | 18 +- .../fields/data_stream_badge.tsx | 32 +++ .../fields/data_streams_field.tsx | 225 ------------------ .../steps/step_settings/fields/index.ts | 1 - .../step_settings/fields/indices_field.tsx | 38 ++- .../steps/step_settings/step_settings.tsx | 13 +- .../sections/policy_add/policy_add.tsx | 11 +- .../sections/policy_edit/policy_edit.tsx | 4 +- .../services/http/policy_requests.ts | 4 +- .../application/services/http/use_request.ts | 4 +- .../server/routes/api/policy.test.ts | 6 +- .../server/routes/api/policy.ts | 20 +- .../server/routes/api/snapshots.test.ts | 1 - .../server/routes/api/validate_schemas.ts | 1 - 22 files changed, 104 insertions(+), 395 deletions(-) create mode 100644 x-pack/plugins/snapshot_restore/common/types/indices.ts delete mode 100644 x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx delete mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts index 84d6ef592ef65..85a3e96fc9b37 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts @@ -114,20 +114,6 @@ describe('', () => { expect(form.getErrorsMessages()).toEqual(['You must select at least one index.']); }); - test('should not require any data streams to be included', async () => { - const { find, form, component } = testBed; - - await act(async () => { - form.toggleEuiSwitch('allDataStreamsToggle', false); - await nextTick(); - component.update(); - }); - - // Deselect all indices from list - find('deselectDataStreamLink').simulate('click'); - - expect(form.getErrorsMessages()).toEqual([]); - }); }); describe('retention (step 3)', () => { diff --git a/x-pack/plugins/snapshot_restore/common/types/index.ts b/x-pack/plugins/snapshot_restore/common/types/index.ts index d52584ca737a2..a12ae904cfee8 100644 --- a/x-pack/plugins/snapshot_restore/common/types/index.ts +++ b/x-pack/plugins/snapshot_restore/common/types/index.ts @@ -8,3 +8,4 @@ export * from './repository'; export * from './snapshot'; export * from './restore'; export * from './policy'; +export * from './indices'; diff --git a/x-pack/plugins/snapshot_restore/common/types/indices.ts b/x-pack/plugins/snapshot_restore/common/types/indices.ts new file mode 100644 index 0000000000000..d9be4657aec03 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/common/types/indices.ts @@ -0,0 +1,14 @@ +/* + * 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. + */ + +export interface Index { + name: string; + dataStream?: string; +} + +export interface PolicyIndicesResponse { + indices: Index[]; +} diff --git a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx deleted file mode 100644 index 0e63714b11b7c..0000000000000 --- a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 React, { useState } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiTitle, EuiLink, EuiIcon, EuiText, EuiSpacer } from '@elastic/eui'; -interface Props { - dataStreams: string[] | string | undefined; -} - -export const CollapsibleDataStreamsList: React.FunctionComponent = ({ dataStreams }) => { - const [isShowingFullDataStreamsList, setIsShowingFullDataStreamsList] = useState(false); - const displayDataStreams = dataStreams - ? typeof dataStreams === 'string' - ? dataStreams.split(',') - : dataStreams - : undefined; - const hiddenDataStreamsCount = - displayDataStreams && displayDataStreams.length > 10 ? displayDataStreams.length - 10 : 0; - return ( - <> - {displayDataStreams ? ( - <> - -
    - {(isShowingFullDataStreamsList - ? displayDataStreams - : [...displayDataStreams].splice(0, 10) - ).map((dataStream) => ( -
  • - - {dataStream} - -
  • - ))} -
-
- {hiddenDataStreamsCount ? ( - <> - - - isShowingFullDataStreamsList - ? setIsShowingFullDataStreamsList(false) - : setIsShowingFullDataStreamsList(true) - } - > - {isShowingFullDataStreamsList ? ( - - ) : ( - - )}{' '} - - - - ) : null} - - ) : ( - - )} - - ); -}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/index.ts index d58edc983c541..439ece284b2da 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/index.ts @@ -5,4 +5,3 @@ */ export { CollapsibleIndicesList } from './collapsible_indices_list'; -export { CollapsibleDataStreamsList } from './collapsible_data_streams_list'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/index.ts index 91266aae66e27..244bc3909e647 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/index.ts @@ -15,7 +15,7 @@ export { SnapshotDeleteProvider } from './snapshot_delete_provider'; export { RestoreSnapshotForm } from './restore_snapshot_form'; export { PolicyExecuteProvider } from './policy_execute_provider'; export { PolicyDeleteProvider } from './policy_delete_provider'; -export { CollapsibleIndicesList, CollapsibleDataStreamsList } from './collapsible_lists'; +export { CollapsibleIndicesList } from './collapsible_lists'; export { RetentionSettingsUpdateModalProvider, UpdateRetentionSettings, diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx index 3fdb3a098a04c..547dc965d90ae 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx @@ -14,7 +14,7 @@ import { EuiSpacer, } from '@elastic/eui'; -import { SlmPolicyPayload } from '../../../../common/types'; +import { SlmPolicyPayload, Index } from '../../../../common/types'; import { TIME_UNITS } from '../../../../common/constants'; import { PolicyValidation, validatePolicy } from '../../services/validation'; import { @@ -27,8 +27,7 @@ import { PolicyNavigation } from './navigation'; interface Props { policy: SlmPolicyPayload; - indices: string[]; - dataStreams: string[]; + indices: Index[]; currentUrl: string; isEditing?: boolean; isSaving: boolean; @@ -41,7 +40,6 @@ interface Props { export const PolicyForm: React.FunctionComponent = ({ policy: originalPolicy, indices, - dataStreams, currentUrl, isEditing, isSaving, @@ -134,7 +132,6 @@ export const PolicyForm: React.FunctionComponent = ({ , validationHelperData?: any) => void; isEditing: boolean; currentUrl: string; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx index 216fefab911e5..a95e0515fef0f 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx @@ -22,7 +22,7 @@ import { import { serializePolicy } from '../../../../../common/lib'; import { useServices } from '../../../app_context'; import { StepProps } from './'; -import { CollapsibleIndicesList, CollapsibleDataStreamsList } from '../../collapsible_lists'; +import { CollapsibleIndicesList } from '../../collapsible_lists'; export const PolicyStepReview: React.FunctionComponent = ({ policy, @@ -30,9 +30,8 @@ export const PolicyStepReview: React.FunctionComponent = ({ }) => { const { i18n } = useServices(); const { name, snapshotName, schedule, repository, config, retention } = policy; - const { indices, includeGlobalState, ignoreUnavailable, partial, dataStreams } = config || { + const { indices, includeGlobalState, ignoreUnavailable, partial } = config || { indices: undefined, - dataStreams: undefined, includeGlobalState: undefined, ignoreUnavailable: undefined, partial: undefined, @@ -158,19 +157,6 @@ export const PolicyStepReview: React.FunctionComponent = ({
- - - - - - - - - - diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx new file mode 100644 index 0000000000000..4df4b53b9a103 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx @@ -0,0 +1,32 @@ +/* + * 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 { EuiBadge, EuiToolTip } from '@elastic/eui'; + +interface Props { + dataStream: string; +} + +export const DataStreamBadge: FunctionComponent = ({ dataStream }) => { + return ( + + + {dataStream} + + + ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx deleted file mode 100644 index 920c0739378d6..0000000000000 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx +++ /dev/null @@ -1,225 +0,0 @@ -/* - * 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 React, { Fragment, FunctionComponent, useState } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { - EuiDescribedFormGroup, - EuiFlexGroup, - EuiFlexItem, - EuiFormRow, - EuiLink, - EuiPanel, - EuiSelectable, - EuiSelectableOption, - EuiSpacer, - EuiSwitch, - EuiTitle, - EuiToolTip, -} from '@elastic/eui'; - -import { SlmPolicyPayload, SnapshotConfig } from '../../../../../../../common/types'; -import { PolicyValidation } from '../../../../../services/validation'; - -interface Props { - isManagedPolicy: boolean; - policy: SlmPolicyPayload; - dataStreams: string[]; - onUpdate: (arg: { dataStreams?: string[] | string }) => void; - errors: PolicyValidation['errors']; -} - -export const DataStreamsField: FunctionComponent = ({ - isManagedPolicy, - dataStreams, - policy, - onUpdate, - errors, -}) => { - const { config = {} } = policy; - const [isAllDataStreams, setIsAllDataStreams] = useState(() => !config.dataStreams); - const [dataStreamsSelection, setDataStreamsSelection] = useState([ - ...dataStreams, - ]); - - // States for choosing all data streams, or a subset, including caching previously chosen subset list - const [dataStreamOptions, setDataStreamOptions] = useState(() => { - return dataStreams.map( - (dataStream): EuiSelectableOption => ({ - label: dataStream, - checked: - isAllDataStreams || - // If dataStreams is a string, we default to custom input mode, so we mark individual data streams - // as selected if user goes back to list mode - typeof config.dataStreams === 'string' || - (Array.isArray(config.dataStreams) && config.dataStreams.includes(dataStream)) - ? 'on' - : undefined, - }) - ); - }); - - const dataStreamsSwitch = ( - - } - checked={isAllDataStreams} - disabled={isManagedPolicy} - data-test-subj="allDataStreamsToggle" - onChange={(e) => { - const isChecked = e.target.checked; - setIsAllDataStreams(isChecked); - if (isChecked) { - onUpdate({ dataStreams: undefined }); - } else { - onUpdate({ - dataStreams: [...(dataStreamsSelection || [])], - }); - } - }} - /> - ); - - return ( - -

- -

- - } - description={ - - } - fullWidth - > - - - {isManagedPolicy ? ( - - -

- } - > - {dataStreamsSwitch} -
- ) : ( - dataStreamsSwitch - )} - {isAllDataStreams ? null : ( - - - - - - - - } - helpText={ - 0 ? ( - { - // TODO: Change this to setDataStreamOptions() when https://github.com/elastic/eui/issues/2071 is fixed - dataStreamOptions.forEach((option: EuiSelectableOption) => { - option.checked = undefined; - }); - onUpdate({ dataStreams: [] }); - setDataStreamsSelection([]); - }} - > - - - ) : ( - { - // TODO: Change this to setDataStreamOptions() when https://github.com/elastic/eui/issues/2071 is fixed - dataStreamOptions.forEach((option: EuiSelectableOption) => { - option.checked = 'on'; - }); - onUpdate({ dataStreams: [...dataStreams] }); - setDataStreamsSelection([...dataStreams]); - }} - > - - - ), - }} - /> - } - isInvalid={Boolean(errors.dataStreams)} - error={errors.dataStreams} - > - { - { - const newSelectedDataStreams: string[] = []; - options.forEach(({ label, checked }) => { - if (checked === 'on') { - newSelectedDataStreams.push(label); - } - }); - setDataStreamOptions(options); - onUpdate({ dataStreams: newSelectedDataStreams }); - setDataStreamsSelection(newSelectedDataStreams); - }} - searchable - height={300} - > - {(list, search) => ( - - {search} - {list} - - )} - - } - - - )} -
-
-
- ); -}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts index 644b8be7818bf..f5c429cb65bbb 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts @@ -5,4 +5,3 @@ */ export { IndicesField } from './indices_field'; -export { DataStreamsField } from './data_streams_field'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx index fb9219b2dcb13..2e9d91d677a0e 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx @@ -23,14 +23,15 @@ import { EuiToolTip, } from '@elastic/eui'; -import { SlmPolicyPayload, SnapshotConfig } from '../../../../../../../common/types'; +import { Index, SlmPolicyPayload, SnapshotConfig } from '../../../../../../../common/types'; import { useServices } from '../../../../../app_context'; import { PolicyValidation } from '../../../../../services/validation'; +import { DataStreamBadge } from './data_stream_badge'; interface Props { isManagedPolicy: boolean; policy: SlmPolicyPayload; - indices: string[]; + indices: Index[]; onUpdate: (arg: { indices?: string[] | string }) => void; errors: PolicyValidation['errors']; } @@ -45,19 +46,22 @@ export const IndicesField: FunctionComponent = ({ const { i18n } = useServices(); const { config = {} } = policy; const [isAllIndices, setIsAllIndices] = useState(!Boolean(config.indices)); - const [indicesSelection, setIndicesSelection] = useState([...indices]); + const [indicesSelection, setIndicesSelection] = useState(() => [ + ...indices.map((i) => i.name), + ]); // States for choosing all indices, or a subset, including caching previously chosen subset list const [indicesOptions, setIndicesOptions] = useState(() => { return indices.map( (index): EuiSelectableOption => ({ - label: index, + label: index.name, + append: index.dataStream ? : undefined, checked: isAllIndices || // If indices is a string, we default to custom input mode, so we mark individual indices // as selected if user goes back to list mode typeof config.indices === 'string' || - (Array.isArray(config.indices) && config.indices.includes(index)) + (Array.isArray(config.indices) && config.indices.includes(index.name)) ? 'on' : undefined, }) @@ -231,8 +235,9 @@ export const IndicesField: FunctionComponent = ({ indicesOptions.forEach((option: EuiSelectableOption) => { option.checked = 'on'; }); - onUpdate({ indices: [...indices] }); - setIndicesSelection([...indices]); + const indicesNames = indices.map((i) => i.name); + onUpdate({ indices: [...indicesNames] }); + setIndicesSelection([...indicesNames]); }} > = ({ ) : ( ({ label: index }))} + options={indices.map((index) => ({ label: index.name, value: index }))} + renderOption={({ value }) => { + return value!.dataStream ? ( + + {value!.name} + + + + + ) : ( + value!.name + ); + }} placeholder={i18n.translate( 'xpack.snapshotRestore.policyForm.stepSettings.indicesPatternPlaceholder', { diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx index ede4f79f4d910..ca8e0d61c7f99 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx @@ -20,12 +20,11 @@ import { SlmPolicyPayload } from '../../../../../../common/types'; import { documentationLinksService } from '../../../../services/documentation'; import { StepProps } from '../'; -import { IndicesField, DataStreamsField } from './fields'; +import { IndicesField } from './fields'; export const PolicyStepSettings: React.FunctionComponent = ({ policy, indices, - dataStreams, updatePolicy, errors, }) => { @@ -133,7 +132,7 @@ export const PolicyStepSettings: React.FunctionComponent = ({ description={ } fullWidth @@ -197,14 +196,6 @@ export const PolicyStepSettings: React.FunctionComponent = ({ onUpdate={updatePolicyConfig} /> - - {renderIgnoreUnavailableField()} {renderPartialField()} {renderIncludeGlobalStateField()} diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/policy_add/policy_add.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/policy_add/policy_add.tsx index 777abb1198a36..5b6637cfd7c1b 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/policy_add/policy_add.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/policy_add/policy_add.tsx @@ -25,14 +25,8 @@ export const PolicyAdd: React.FunctionComponent = ({ const [isSaving, setIsSaving] = useState(false); const [saveError, setSaveError] = useState(null); - const { - error: errorLoadingIndices, - isLoading: isLoadingIndices, - data: { indices, dataStreams } = { - indices: [], - dataStreams: [], - }, - } = useLoadIndices(); + const { error: errorLoadingIndices, isLoading: isLoadingIndices, data } = useLoadIndices(); + const { indices } = data ?? { indices: [] }; // Set breadcrumb and page title useEffect(() => { @@ -124,7 +118,6 @@ export const PolicyAdd: React.FunctionComponent = ({ { }; export const useLoadIndices = () => { - return useRequest({ + return useRequest({ path: `${API_BASE_PATH}policies/indices`, method: 'get', }); diff --git a/x-pack/plugins/snapshot_restore/public/application/services/http/use_request.ts b/x-pack/plugins/snapshot_restore/public/application/services/http/use_request.ts index 27a565ccb74bc..b4d0493098bbc 100644 --- a/x-pack/plugins/snapshot_restore/public/application/services/http/use_request.ts +++ b/x-pack/plugins/snapshot_restore/public/application/services/http/use_request.ts @@ -18,6 +18,6 @@ export const sendRequest = (config: SendRequestConfig) => { return _sendRequest(httpService.httpClient, config); }; -export const useRequest = (config: UseRequestConfig) => { - return _useRequest(httpService.httpClient, config); +export const useRequest = (config: UseRequestConfig) => { + return _useRequest(httpService.httpClient, config); }; diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/policy.test.ts b/x-pack/plugins/snapshot_restore/server/routes/api/policy.test.ts index 17a8ebc9a5da0..7a76f4b4d3518 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/policy.test.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/policy.test.ts @@ -334,13 +334,14 @@ describe('[Snapshot and Restore API Routes] Policy', () => { { name: 'barIndex', attributes: ['open'], + data_stream: 'testDataStream', }, ], aliases: [], data_streams: [ { name: 'testDataStream', - backing_indices: '.ds-test-data-stream-000001', + backing_indices: 'barIndex', timestamp_field: '@timestamp', }, ], @@ -349,7 +350,6 @@ describe('[Snapshot and Restore API Routes] Policy', () => { const expectedResponse = { indices: ['barIndex', 'fooIndex'], - dataStreams: ['testDataStream'], }; await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); }); @@ -362,7 +362,7 @@ describe('[Snapshot and Restore API Routes] Policy', () => { }; router.callAsCurrentUserResponses = [mockEsResponse]; - const expectedResponse = { indices: [], dataStreams: [] }; + const expectedResponse = { indices: [] }; await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); }); diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts b/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts index b23a03b474099..7d483a16e05f7 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts @@ -5,7 +5,7 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; -import { SlmPolicyEs } from '../../../common/types'; +import { SlmPolicyEs, PolicyIndicesResponse } from '../../../common/types'; import { deserializePolicy, serializePolicy } from '../../../common/lib'; import { getManagedPolicyNames } from '../../lib'; import { RouteDependencies, ResolveIndexResponseFromES } from '../../types'; @@ -243,18 +243,14 @@ export function registerPolicyRoutes({ } ); + const body: PolicyIndicesResponse = { + indices: resolvedIndicesResponse.indices + .map(({ name, data_stream }) => ({ name, dataStream: data_stream })) + .sort((a, b) => a.name.localeCompare(b.name)), + }; + return res.ok({ - body: { - indices: resolvedIndicesResponse.indices - .flatMap((index) => { - if (index.data_stream) { - return []; - } - return index.name; - }) - .sort(), - dataStreams: resolvedIndicesResponse.data_streams.map(({ name }) => name).sort(), - }, + body, }); } catch (e) { if (isEsError(e)) { diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.test.ts b/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.test.ts index bfe7e96493279..f913299fc3992 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.test.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.test.ts @@ -14,7 +14,6 @@ const defaultSnapshot = { uuid: undefined, versionId: undefined, version: undefined, - dataStreams: [], indices: [], includeGlobalState: undefined, state: undefined, diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts b/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts index 0ce3de6a6e061..e5df0ec33db0b 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts @@ -11,7 +11,6 @@ export const nameParameterSchema = schema.object({ const snapshotConfigSchema = schema.object({ indices: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), - dataStreams: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), ignoreUnavailable: schema.maybe(schema.boolean()), includeGlobalState: schema.maybe(schema.boolean()), partial: schema.maybe(schema.boolean()), From 31768faf8f81d3cc69885acc7606864a2e2a9cb6 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 24 Jun 2020 14:24:15 +0200 Subject: [PATCH 11/43] added data stream to snapshot summary details --- .../collapsible_data_streams_list.tsx | 77 +++++++++++++++++++ .../components/collapsible_lists/index.ts | 1 + .../fields => }/data_stream_badge.tsx | 0 .../public/application/components/index.ts | 2 +- .../step_settings/fields/indices_field.tsx | 2 +- .../snapshot_details/tabs/tab_summary.tsx | 18 +++++ 6 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx rename x-pack/plugins/snapshot_restore/public/application/components/{policy_form/steps/step_settings/fields => }/data_stream_badge.tsx (100%) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx new file mode 100644 index 0000000000000..4f9ef66bb598f --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx @@ -0,0 +1,77 @@ +/* + * 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 React, { useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiTitle, EuiLink, EuiIcon, EuiText, EuiSpacer } from '@elastic/eui'; +interface Props { + dataStreams: string[] | string | undefined; +} + +export const CollapsibleDataStreamsList: React.FunctionComponent = ({ dataStreams }) => { + const [isShowingFullDataStreamsList, setIsShowingFullDataStreamsList] = useState(false); + const displayDataStreams = dataStreams + ? typeof dataStreams === 'string' + ? dataStreams.split(',') + : dataStreams + : undefined; + const hiddenDataStreams = + displayDataStreams && displayDataStreams.length > 10 ? displayDataStreams.length - 10 : 0; + return ( + <> + {displayDataStreams ? ( + <> + +
    + {(isShowingFullDataStreamsList + ? displayDataStreams + : [...displayDataStreams].splice(0, 10) + ).map((dataStream) => ( +
  • + + {dataStream} + +
  • + ))} +
+
+ {hiddenDataStreams ? ( + <> + + + isShowingFullDataStreamsList + ? setIsShowingFullDataStreamsList(false) + : setIsShowingFullDataStreamsList(true) + } + > + {isShowingFullDataStreamsList ? ( + + ) : ( + + )}{' '} + + + + ) : null} + + ) : ( + + )} + + ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/index.ts index 439ece284b2da..d58edc983c541 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/index.ts @@ -5,3 +5,4 @@ */ export { CollapsibleIndicesList } from './collapsible_indices_list'; +export { CollapsibleDataStreamsList } from './collapsible_data_streams_list'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx b/x-pack/plugins/snapshot_restore/public/application/components/data_stream_badge.tsx similarity index 100% rename from x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx rename to x-pack/plugins/snapshot_restore/public/application/components/data_stream_badge.tsx diff --git a/x-pack/plugins/snapshot_restore/public/application/components/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/index.ts index 244bc3909e647..91266aae66e27 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/index.ts @@ -15,7 +15,7 @@ export { SnapshotDeleteProvider } from './snapshot_delete_provider'; export { RestoreSnapshotForm } from './restore_snapshot_form'; export { PolicyExecuteProvider } from './policy_execute_provider'; export { PolicyDeleteProvider } from './policy_delete_provider'; -export { CollapsibleIndicesList } from './collapsible_lists'; +export { CollapsibleIndicesList, CollapsibleDataStreamsList } from './collapsible_lists'; export { RetentionSettingsUpdateModalProvider, UpdateRetentionSettings, diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx index 2e9d91d677a0e..dcc01abe3137b 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx @@ -26,7 +26,7 @@ import { import { Index, SlmPolicyPayload, SnapshotConfig } from '../../../../../../../common/types'; import { useServices } from '../../../../../app_context'; import { PolicyValidation } from '../../../../../services/validation'; -import { DataStreamBadge } from './data_stream_badge'; +import { DataStreamBadge } from '../../../../data_stream_badge'; interface Props { isManagedPolicy: boolean; diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_details/tabs/tab_summary.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_details/tabs/tab_summary.tsx index 287a77493307d..1a0c26c854490 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_details/tabs/tab_summary.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/snapshot_list/snapshot_details/tabs/tab_summary.tsx @@ -22,6 +22,7 @@ import { DataPlaceholder, FormattedDateTime, CollapsibleIndicesList, + CollapsibleDataStreamsList, } from '../../../../../components'; import { linkToPolicy } from '../../../../../services/navigation'; import { SnapshotState } from './snapshot_state'; @@ -40,6 +41,7 @@ export const TabSummary: React.FC = ({ snapshotDetails }) => { // TODO: Add a tooltip explaining that: a false value means that the cluster global state // is not stored as part of the snapshot. includeGlobalState, + dataStreams, indices, state, startTimeInMillis, @@ -135,6 +137,22 @@ export const TabSummary: React.FC = ({ snapshotDetails }) => {
+ + + + + + + + + + + + From 12a4e80ade6813f794f8315a5699b2db57cfdd2e Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 24 Jun 2020 14:25:10 +0200 Subject: [PATCH 12/43] move the data streams badge file closer to where it used --- .../steps/step_settings/fields}/data_stream_badge.tsx | 0 .../policy_form/steps/step_settings/fields/indices_field.tsx | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename x-pack/plugins/snapshot_restore/public/application/components/{ => policy_form/steps/step_settings/fields}/data_stream_badge.tsx (100%) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/data_stream_badge.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx similarity index 100% rename from x-pack/plugins/snapshot_restore/public/application/components/data_stream_badge.tsx rename to x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx index dcc01abe3137b..2e9d91d677a0e 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx @@ -26,7 +26,7 @@ import { import { Index, SlmPolicyPayload, SnapshotConfig } from '../../../../../../../common/types'; import { useServices } from '../../../../../app_context'; import { PolicyValidation } from '../../../../../services/validation'; -import { DataStreamBadge } from '../../../../data_stream_badge'; +import { DataStreamBadge } from './data_stream_badge'; interface Props { isManagedPolicy: boolean; From 23cd98b7a5efa8bfb59669150cd0121f7628dff0 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 24 Jun 2020 14:37:16 +0200 Subject: [PATCH 13/43] add data stream badge when restoring snapshots too --- .../restore_snapshot_form/steps/index.ts | 2 +- .../step_logistics/data_stream_badge.tsx | 30 ++++++++++++++++ .../steps/step_logistics/index.ts | 7 ++++ .../{ => step_logistics}/step_logistics.tsx | 35 ++++++++++++++++--- 4 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_stream_badge.tsx create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/index.ts rename x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/{ => step_logistics}/step_logistics.tsx (94%) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/index.ts index 3f3db0ff28eca..182d4ef8f583a 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/index.ts @@ -14,6 +14,6 @@ export interface StepProps { updateCurrentStep: (step: number) => void; } -export { RestoreSnapshotStepLogistics } from './step_logistics'; +export { RestoreSnapshotStepLogistics } from './step_logistics/step_logistics'; export { RestoreSnapshotStepSettings } from './step_settings'; export { RestoreSnapshotStepReview } from './step_review'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_stream_badge.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_stream_badge.tsx new file mode 100644 index 0000000000000..042d9d6df2e6d --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_stream_badge.tsx @@ -0,0 +1,30 @@ +/* + * 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 { EuiBadge, EuiToolTip } from '@elastic/eui'; + +export const DataStreamBadge: FunctionComponent = () => { + return ( + + + {i18n.translate( + 'xpack.snapshotRestore.restoreForm.stepLogistics.backingIndexBadgeContent', + { defaultMessage: 'Backing index' } + )} + + + ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/index.ts new file mode 100644 index 0000000000000..8f4efcf2a91f1 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { RestoreSnapshotStepLogistics } from './step_logistics'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx similarity index 94% rename from x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics.tsx rename to x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index c80c5a2e4c01d..cfe31e14b3c23 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -21,10 +21,17 @@ import { EuiComboBox, } from '@elastic/eui'; import { EuiSelectableOption } from '@elastic/eui'; -import { RestoreSettings } from '../../../../../common/types'; -import { documentationLinksService } from '../../../services/documentation'; -import { useServices } from '../../../app_context'; -import { StepProps } from './'; + +import { isDataStreamBackingIndex } from '../../../../../../common/lib'; +import { RestoreSettings } from '../../../../../../common/types'; + +import { documentationLinksService } from '../../../../services/documentation'; + +import { useServices } from '../../../../app_context'; + +import { DataStreamBadge } from './data_stream_badge'; + +import { StepProps } from '../index'; export const RestoreSnapshotStepLogistics: React.FunctionComponent = ({ snapshotDetails, @@ -52,6 +59,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = snapshotIndices.map( (index): EuiSelectableOption => ({ label: index, + append: isDataStreamBackingIndex(index) ? : undefined, checked: isAllIndices || // If indices is a string, we default to custom input mode, so we mark individual indices @@ -302,7 +310,24 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = ) : ( ({ label: index }))} + options={snapshotIndices.map((index) => ({ label: index, value: index }))} + renderOption={({ value }) => { + return isDataStreamBackingIndex(value!) ? ( + + {value!} + + + + + ) : ( + value! + ); + }} placeholder={i18n.translate( 'xpack.snapshotRestore.restoreForm.stepLogistics.indicesPatternPlaceholder', { From ad0b6c6ba9994fdafd8170532e23057517391b84 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 24 Jun 2020 15:24:34 +0200 Subject: [PATCH 14/43] update restore copy --- .../steps/step_logistics/step_logistics.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index cfe31e14b3c23..b7ef0526d9336 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -526,7 +526,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = } fullWidth From f57af3c6fb6dc41b15b53fc6acae9b235a9593c2 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 25 Jun 2020 12:21:09 +0200 Subject: [PATCH 15/43] fix pattern specification in indices and data streams field --- .../fields/data_stream_badge.tsx | 32 --- .../fields/data_streams_field.tsx | 227 ++++++++++++++++++ .../step_settings/fields/indices_field.tsx | 92 ++++--- 3 files changed, 270 insertions(+), 81 deletions(-) delete mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx deleted file mode 100644 index 4df4b53b9a103..0000000000000 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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 { EuiBadge, EuiToolTip } from '@elastic/eui'; - -interface Props { - dataStream: string; -} - -export const DataStreamBadge: FunctionComponent = ({ dataStream }) => { - return ( - - - {dataStream} - - - ); -}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx new file mode 100644 index 0000000000000..6b3b2f4316f94 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx @@ -0,0 +1,227 @@ +/* + * 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 React, { Fragment, FunctionComponent, useState } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; + +import { + EuiDescribedFormGroup, + EuiFlexGroup, + EuiFlexItem, + EuiFormRow, + EuiLink, + EuiPanel, + EuiSelectable, + EuiSelectableOption, + EuiSpacer, + EuiSwitch, + EuiTitle, + EuiToolTip, +} from '@elastic/eui'; + +import { SlmPolicyPayload, SnapshotConfig } from '../../../../../../../common/types'; +import { PolicyValidation } from '../../../../../services/validation'; + +interface Props { + isManagedPolicy: boolean; + policy: SlmPolicyPayload; + dataStreams: string[]; + onUpdate: (arg: { dataStreams?: string[] | string }) => void; + errors: PolicyValidation['errors']; +} + +export const DataStreamsField: FunctionComponent = ({ + isManagedPolicy, + dataStreams, + policy, + onUpdate, + errors, +}) => { + const { config = {} } = policy; + const [isAllDataStreams, setIsAllDataStreams] = useState( + !config.dataStreams || (Array.isArray(config.dataStreams) && config.dataStreams.length === 0) + ); + const [dataStreamsSelection, setDataStreamsSelection] = useState([ + ...dataStreams, + ]); + + // States for choosing all data streams, or a subset, including caching previously chosen subset list + const [dataStreamOptions, setDataStreamOptions] = useState(() => { + return dataStreams.map( + (dataStream): EuiSelectableOption => ({ + label: dataStream, + checked: + isAllDataStreams || + // If dataStreams is a string, we default to custom input mode, so we mark individual data streams + // as selected if user goes back to list mode + typeof config.dataStreams === 'string' || + (Array.isArray(config.dataStreams) && config.dataStreams.includes(dataStream)) + ? 'on' + : undefined, + }) + ); + }); + + const dataStreamsSwitch = ( + + } + checked={isAllDataStreams} + disabled={isManagedPolicy} + data-test-subj="allDataStreamsToggle" + onChange={(e) => { + const isChecked = e.target.checked; + setIsAllDataStreams(isChecked); + if (isChecked) { + onUpdate({ dataStreams: undefined }); + } else { + onUpdate({ + dataStreams: [...(dataStreamsSelection || [])], + }); + } + }} + /> + ); + + return ( + +

+ +

+ + } + description={ + + } + fullWidth + > + + + {isManagedPolicy ? ( + + +

+ } + > + {dataStreamsSwitch} +
+ ) : ( + dataStreamsSwitch + )} + {isAllDataStreams ? null : ( + + + + + + +
+ } + helpText={ + 0 ? ( + { + // TODO: Change this to setDataStreamOptions() when https://github.com/elastic/eui/issues/2071 is fixed + dataStreamOptions.forEach((option: EuiSelectableOption) => { + option.checked = undefined; + }); + onUpdate({ dataStreams: [] }); + setDataStreamsSelection([]); + }} + > + + + ) : ( + { + // TODO: Change this to setDataStreamOptions() when https://github.com/elastic/eui/issues/2071 is fixed + dataStreamOptions.forEach((option: EuiSelectableOption) => { + option.checked = 'on'; + }); + onUpdate({ dataStreams: [...dataStreams] }); + setDataStreamsSelection([...dataStreams]); + }} + > + + + ), + }} + /> + } + isInvalid={Boolean(errors.dataStreams)} + error={errors.dataStreams} + > + { + { + const newSelectedDataStreams: string[] = []; + options.forEach(({ label, checked }) => { + if (checked === 'on') { + newSelectedDataStreams.push(label); + } + }); + setDataStreamOptions(options); + onUpdate({ dataStreams: newSelectedDataStreams }); + setDataStreamsSelection(newSelectedDataStreams); + }} + searchable + height={300} + > + {(list, search) => ( + + {search} + {list} + + )} + + } + + + )} + + + + ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx index 2e9d91d677a0e..870946e0a2c3b 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx @@ -23,15 +23,14 @@ import { EuiToolTip, } from '@elastic/eui'; -import { Index, SlmPolicyPayload, SnapshotConfig } from '../../../../../../../common/types'; +import { SlmPolicyPayload } from '../../../../../../../common/types'; import { useServices } from '../../../../../app_context'; import { PolicyValidation } from '../../../../../services/validation'; -import { DataStreamBadge } from './data_stream_badge'; interface Props { isManagedPolicy: boolean; policy: SlmPolicyPayload; - indices: Index[]; + indices: string[]; onUpdate: (arg: { indices?: string[] | string }) => void; errors: PolicyValidation['errors']; } @@ -45,42 +44,55 @@ export const IndicesField: FunctionComponent = ({ }) => { const { i18n } = useServices(); const { config = {} } = policy; - const [isAllIndices, setIsAllIndices] = useState(!Boolean(config.indices)); - const [indicesSelection, setIndicesSelection] = useState(() => [ - ...indices.map((i) => i.name), - ]); + + // We assume all indices if the config has no indices entry or if we receive an empty array + const [isAllIndices, setIsAllIndices] = useState( + !config.indices || (Array.isArray(config.indices) && config.indices.length === 0) + ); + const [indicesSelection, setIndicesSelection] = useState(() => + Array.isArray(config.indices) && !isAllIndices + ? indices.filter((i) => (config.indices! as string[]).includes(i)) + : [...indices] + ); // States for choosing all indices, or a subset, including caching previously chosen subset list - const [indicesOptions, setIndicesOptions] = useState(() => { - return indices.map( - (index): EuiSelectableOption => ({ - label: index.name, - append: index.dataStream ? : undefined, - checked: - isAllIndices || - // If indices is a string, we default to custom input mode, so we mark individual indices - // as selected if user goes back to list mode - typeof config.indices === 'string' || - (Array.isArray(config.indices) && config.indices.includes(index.name)) - ? 'on' - : undefined, - }) - ); - }); + const [indicesOptions, setIndicesOptions] = useState(() => + indices.map( + (index): EuiSelectableOption => { + return { + label: index, + checked: + isAllIndices || + // If indices is a string, we default to custom input mode, so we mark individual indices + // as selected if user goes back to list mode + typeof config.indices === 'string' || + indicesSelection.includes(index) + ? 'on' + : undefined, + }; + } + ) + ); // State for using selectable indices list or custom patterns // Users with more than 100 indices will probably want to use an index pattern to select - // them instead, so we'll default to showing them the index pattern input. - const [selectIndicesMode, setSelectIndicesMode] = useState<'list' | 'custom'>( + // them instead, so we'll default to showing them the index pattern input. Also show the custom + // list if we have no exact matches in the configured array to some existing index. + const [selectIndicesMode, setSelectIndicesMode] = useState<'list' | 'custom'>(() => typeof config.indices === 'string' || - (Array.isArray(config.indices) && config.indices.length > 100) + (Array.isArray(config.indices) && + (config.indices.length > 100 || !config.indices.every((c) => indices.some((i) => i === c)))) ? 'custom' : 'list' ); // State for custom patterns - const [indexPatterns, setIndexPatterns] = useState( - typeof config.indices === 'string' ? (config.indices as string).split(',') : [] + const [indexPatterns, setIndexPatterns] = useState(() => + typeof config.indices === 'string' + ? (config.indices as string).split(',') + : Array.isArray(config.indices) + ? config.indices + : [] ); const indicesSwitch = ( @@ -235,9 +247,8 @@ export const IndicesField: FunctionComponent = ({ indicesOptions.forEach((option: EuiSelectableOption) => { option.checked = 'on'; }); - const indicesNames = indices.map((i) => i.name); - onUpdate({ indices: [...indicesNames] }); - setIndicesSelection([...indicesNames]); + onUpdate({ indices: [...indices] }); + setIndicesSelection([...indices]); }} > = ({ ) : ( ({ label: index.name, value: index }))} - renderOption={({ value }) => { - return value!.dataStream ? ( - - {value!.name} - - - - - ) : ( - value!.name - ); - }} + options={indices.map((index) => ({ label: index }))} placeholder={i18n.translate( 'xpack.snapshotRestore.policyForm.stepSettings.indicesPatternPlaceholder', { From f5134743a8b5d07b79a40cf598c2d40108b1b20f Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 25 Jun 2020 16:14:23 +0200 Subject: [PATCH 16/43] first iteration of complete policy UX --- .../helpers/policy_form.helpers.ts | 2 ++ .../client_integration/policy_add.test.ts | 14 +++++++- .../common/lib/snapshot_serialization.ts | 2 ++ .../snapshot_restore/common/types/indices.ts | 8 ++--- .../components/policy_form/policy_form.tsx | 7 ++-- .../components/policy_form/steps/index.ts | 5 +-- .../policy_form/steps/step_review.tsx | 18 ++++++++-- .../fields/data_streams_field.tsx | 22 ++++++++---- .../steps/step_settings/fields/index.ts | 1 + .../steps/step_settings/step_settings.tsx | 11 +++++- .../sections/policy_add/policy_add.tsx | 3 +- .../sections/policy_edit/policy_edit.tsx | 24 +++++++++---- .../separate_data_streams_from_indices.ts | 36 +++++++++++++++++++ .../services/validation/validate_policy.ts | 32 +++++++++++------ .../server/routes/api/policy.test.ts | 7 ++-- .../server/routes/api/policy.ts | 5 +-- .../server/routes/api/snapshots.test.ts | 1 + .../server/routes/api/validate_schemas.ts | 1 + .../plugins/snapshot_restore/server/types.ts | 2 +- .../test/fixtures/snapshot.ts | 1 + 20 files changed, 158 insertions(+), 44 deletions(-) create mode 100644 x-pack/plugins/snapshot_restore/public/application/sections/policy_edit/separate_data_streams_from_indices.ts diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/policy_form.helpers.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/policy_form.helpers.ts index 131969b997b53..70f3cdafc427a 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/policy_form.helpers.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/policy_form.helpers.ts @@ -41,6 +41,8 @@ export type PolicyFormTestSubjects = | 'allIndicesToggle' | 'backButton' | 'deselectIndicesLink' + | 'allDataStreamsToggle' + | 'deselectDataStreamLink' | 'expireAfterValueInput' | 'expireAfterUnitSelect' | 'ignoreUnavailableIndicesToggle' diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts index 85a3e96fc9b37..79621fc2f1fc1 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts @@ -99,7 +99,7 @@ describe('', () => { actions.clickNextButton(); }); - test('should require at least one index', async () => { + test('should require at least one index if no data streams are provided', async () => { const { find, form, component } = testBed; await act(async () => { @@ -114,6 +114,18 @@ describe('', () => { expect(form.getErrorsMessages()).toEqual(['You must select at least one index.']); }); + test('should not require at least one index if a data stream is provided', async () => { + const { form, component } = testBed; + + await act(async () => { + // Toggle "All data streams" switch. Not all data streams are selected by default. + form.toggleEuiSwitch('allDataStreamsToggle', false); + await nextTick(); + component.update(); + }); + + expect(form.getErrorsMessages()).toEqual([]); + }); }); describe('retention (step 3)', () => { diff --git a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts index 33efdc8bc9550..562c083436b27 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts @@ -139,6 +139,8 @@ export function serializeSnapshotConfig(snapshotConfig: SnapshotConfig): Snapsho } = snapshotConfig; const indicesArray = indicesToArray(indices); + // Even though data streams are not indices, we can treat the input the same way + // we treat input for the indices field because it gets concatenated to it. const dataStreamsArray = indicesToArray(dataStreams); const snapshotConfigEs: SnapshotConfigEs = { diff --git a/x-pack/plugins/snapshot_restore/common/types/indices.ts b/x-pack/plugins/snapshot_restore/common/types/indices.ts index d9be4657aec03..e6464dfe72da8 100644 --- a/x-pack/plugins/snapshot_restore/common/types/indices.ts +++ b/x-pack/plugins/snapshot_restore/common/types/indices.ts @@ -4,11 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -export interface Index { - name: string; - dataStream?: string; -} - export interface PolicyIndicesResponse { - indices: Index[]; + dataStreams: string[]; + indices: string[]; } diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx index 547dc965d90ae..cb9ecda787cfc 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx @@ -14,7 +14,7 @@ import { EuiSpacer, } from '@elastic/eui'; -import { SlmPolicyPayload, Index } from '../../../../common/types'; +import { SlmPolicyPayload } from '../../../../common/types'; import { TIME_UNITS } from '../../../../common/constants'; import { PolicyValidation, validatePolicy } from '../../services/validation'; import { @@ -27,7 +27,8 @@ import { PolicyNavigation } from './navigation'; interface Props { policy: SlmPolicyPayload; - indices: Index[]; + dataStreams: string[]; + indices: string[]; currentUrl: string; isEditing?: boolean; isSaving: boolean; @@ -39,6 +40,7 @@ interface Props { export const PolicyForm: React.FunctionComponent = ({ policy: originalPolicy, + dataStreams, indices, currentUrl, isEditing, @@ -132,6 +134,7 @@ export const PolicyForm: React.FunctionComponent = ({ , validationHelperData?: any) => void; isEditing: boolean; currentUrl: string; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx index a95e0515fef0f..b8c5bab6a7ccf 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx @@ -22,7 +22,7 @@ import { import { serializePolicy } from '../../../../../common/lib'; import { useServices } from '../../../app_context'; import { StepProps } from './'; -import { CollapsibleIndicesList } from '../../collapsible_lists'; +import { CollapsibleIndicesList, CollapsibleDataStreamsList } from '../../collapsible_lists'; export const PolicyStepReview: React.FunctionComponent = ({ policy, @@ -30,8 +30,9 @@ export const PolicyStepReview: React.FunctionComponent = ({ }) => { const { i18n } = useServices(); const { name, snapshotName, schedule, repository, config, retention } = policy; - const { indices, includeGlobalState, ignoreUnavailable, partial } = config || { + const { indices, includeGlobalState, ignoreUnavailable, partial, dataStreams } = config || { indices: undefined, + dataStreams: undefined, includeGlobalState: undefined, ignoreUnavailable: undefined, partial: undefined, @@ -157,6 +158,19 @@ export const PolicyStepReview: React.FunctionComponent = ({ + + + + + + + + + + diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx index 6b3b2f4316f94..4cd92c4763d41 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx @@ -22,7 +22,7 @@ import { EuiToolTip, } from '@elastic/eui'; -import { SlmPolicyPayload, SnapshotConfig } from '../../../../../../../common/types'; +import { SlmPolicyPayload } from '../../../../../../../common/types'; import { PolicyValidation } from '../../../../../services/validation'; interface Props { @@ -41,12 +41,22 @@ export const DataStreamsField: FunctionComponent = ({ errors, }) => { const { config = {} } = policy; + + // No data streams are selected by default const [isAllDataStreams, setIsAllDataStreams] = useState( - !config.dataStreams || (Array.isArray(config.dataStreams) && config.dataStreams.length === 0) + () => + Array.isArray(config.dataStreams) && + config.dataStreams.length > 0 && + config.dataStreams.every((d) => dataStreams.includes(d)) + ); + + const [dataStreamsSelection, setDataStreamsSelection] = useState( + isAllDataStreams + ? [...dataStreams] + : Array.isArray(config.dataStreams) + ? dataStreams.filter((d) => (config.dataStreams! as string[]).includes(d)) + : [] ); - const [dataStreamsSelection, setDataStreamsSelection] = useState([ - ...dataStreams, - ]); // States for choosing all data streams, or a subset, including caching previously chosen subset list const [dataStreamOptions, setDataStreamOptions] = useState(() => { @@ -80,7 +90,7 @@ export const DataStreamsField: FunctionComponent = ({ const isChecked = e.target.checked; setIsAllDataStreams(isChecked); if (isChecked) { - onUpdate({ dataStreams: undefined }); + onUpdate({ dataStreams: [...dataStreams] }); } else { onUpdate({ dataStreams: [...(dataStreamsSelection || [])], diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts index f5c429cb65bbb..644b8be7818bf 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts @@ -5,3 +5,4 @@ */ export { IndicesField } from './indices_field'; +export { DataStreamsField } from './data_streams_field'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx index ca8e0d61c7f99..66072ce314b9f 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx @@ -20,10 +20,11 @@ import { SlmPolicyPayload } from '../../../../../../common/types'; import { documentationLinksService } from '../../../../services/documentation'; import { StepProps } from '../'; -import { IndicesField } from './fields'; +import { IndicesField, DataStreamsField } from './fields'; export const PolicyStepSettings: React.FunctionComponent = ({ policy, + dataStreams, indices, updatePolicy, errors, @@ -196,6 +197,14 @@ export const PolicyStepSettings: React.FunctionComponent = ({ onUpdate={updatePolicyConfig} /> + + {renderIgnoreUnavailableField()} {renderPartialField()} {renderIncludeGlobalStateField()} diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/policy_add/policy_add.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/policy_add/policy_add.tsx index 5b6637cfd7c1b..90cd26c821c5e 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/policy_add/policy_add.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/policy_add/policy_add.tsx @@ -26,7 +26,7 @@ export const PolicyAdd: React.FunctionComponent = ({ const [saveError, setSaveError] = useState(null); const { error: errorLoadingIndices, isLoading: isLoadingIndices, data } = useLoadIndices(); - const { indices } = data ?? { indices: [] }; + const { indices, dataStreams } = data ?? { indices: [], dataStreams: [] }; // Set breadcrumb and page title useEffect(() => { @@ -118,6 +118,7 @@ export const PolicyAdd: React.FunctionComponent = ({ { - if (policyData && policyData.policy) { - setPolicy(policyData.policy); + if (policyData && policyData.policy && indicesData) { + const indicesAndDataStreams = separateDataStreamsFromIndices( + indicesData, + policyData.policy.config?.indices ?? [] + ); + setPolicy({ + ...policyData.policy, + config: { + ...policyData.policy.config, + ...indicesAndDataStreams, + }, + }); } - }, [policyData]); + }, [policyData, indicesData]); // Saving policy states const [isSaving, setIsSaving] = useState(false); @@ -200,7 +209,8 @@ export const PolicyEdit: React.FunctionComponent { + const configuredPatternsArray = indicesToArray(configuredPatterns); + const result: Result = { + dataStreams: [], + indices: [], + }; + for (const indexOrDataStreamPattern of configuredPatternsArray) { + if (dataStreams.some((ds) => ds === indexOrDataStreamPattern)) { + result.dataStreams.push(indexOrDataStreamPattern); + } else { + result.indices.push(indexOrDataStreamPattern); + } + } + return result; +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_policy.ts b/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_policy.ts index 0720994ca7669..112522a53553f 100644 --- a/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_policy.ts +++ b/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_policy.ts @@ -95,20 +95,32 @@ export const validatePolicy = ( ); } - if (config && typeof config.indices === 'string' && config.indices.trim().length === 0) { - validation.errors.indices.push( - i18n.translate('xpack.snapshotRestore.policyValidation.indexPatternRequiredErrorMessage', { - defaultMessage: 'At least one index pattern is required.', - }) + const hasDataStreams = () => { + return ( + config && + ((typeof config.dataStreams === 'string' && config.dataStreams.trim().length > 0) || + (Array.isArray(config.dataStreams) && config.dataStreams.length > 0)) ); + }; + + if (config && typeof config.indices === 'string' && config.indices.trim().length === 0) { + if (!hasDataStreams()) { + validation.errors.indices.push( + i18n.translate('xpack.snapshotRestore.policyValidation.indexPatternRequiredErrorMessage', { + defaultMessage: 'At least one index pattern is required.', + }) + ); + } } if (config && Array.isArray(config.indices) && config.indices.length === 0) { - validation.errors.indices.push( - i18n.translate('xpack.snapshotRestore.policyValidation.indicesRequiredErrorMessage', { - defaultMessage: 'You must select at least one index.', - }) - ); + if (!hasDataStreams()) { + validation.errors.indices.push( + i18n.translate('xpack.snapshotRestore.policyValidation.indicesRequiredErrorMessage', { + defaultMessage: 'You must select at least one index.', + }) + ); + } } if ( diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/policy.test.ts b/x-pack/plugins/snapshot_restore/server/routes/api/policy.test.ts index 7a76f4b4d3518..b96d305fa4a87 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/policy.test.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/policy.test.ts @@ -341,7 +341,7 @@ describe('[Snapshot and Restore API Routes] Policy', () => { data_streams: [ { name: 'testDataStream', - backing_indices: 'barIndex', + backing_indices: ['barIndex'], timestamp_field: '@timestamp', }, ], @@ -349,7 +349,8 @@ describe('[Snapshot and Restore API Routes] Policy', () => { router.callAsCurrentUserResponses = [mockEsResponse]; const expectedResponse = { - indices: ['barIndex', 'fooIndex'], + indices: ['fooIndex'], + dataStreams: ['testDataStream'], }; await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); }); @@ -362,7 +363,7 @@ describe('[Snapshot and Restore API Routes] Policy', () => { }; router.callAsCurrentUserResponses = [mockEsResponse]; - const expectedResponse = { indices: [] }; + const expectedResponse = { indices: [], dataStreams: [] }; await expect(router.runRequest(mockRequest)).resolves.toEqual({ body: expectedResponse }); }); diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts b/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts index 7d483a16e05f7..b8e7012529554 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts @@ -244,9 +244,10 @@ export function registerPolicyRoutes({ ); const body: PolicyIndicesResponse = { + dataStreams: resolvedIndicesResponse.data_streams.map(({ name }) => name).sort(), indices: resolvedIndicesResponse.indices - .map(({ name, data_stream }) => ({ name, dataStream: data_stream })) - .sort((a, b) => a.name.localeCompare(b.name)), + .flatMap((index) => (index.data_stream ? [] : index.name)) + .sort(), }; return res.ok({ diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.test.ts b/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.test.ts index f913299fc3992..a7e61d1e7c02a 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.test.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.test.ts @@ -15,6 +15,7 @@ const defaultSnapshot = { versionId: undefined, version: undefined, indices: [], + dataStreams: [], includeGlobalState: undefined, state: undefined, startTime: undefined, diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts b/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts index e5df0ec33db0b..953f61b4ff128 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts @@ -10,6 +10,7 @@ export const nameParameterSchema = schema.object({ }); const snapshotConfigSchema = schema.object({ + dataStreams: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), indices: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), ignoreUnavailable: schema.maybe(schema.boolean()), includeGlobalState: schema.maybe(schema.boolean()), diff --git a/x-pack/plugins/snapshot_restore/server/types.ts b/x-pack/plugins/snapshot_restore/server/types.ts index 2d71b34289f75..8d1735e7a5e18 100644 --- a/x-pack/plugins/snapshot_restore/server/types.ts +++ b/x-pack/plugins/snapshot_restore/server/types.ts @@ -44,7 +44,7 @@ interface DataObjectFromES { export interface ResolveIndexResponseFromES { indices: DataObjectFromES[]; aliases: DataObjectFromES[]; - data_streams: Array>; + data_streams: Array<{ name: string; backing_indices: string[]; timestamp_field: string }>; } export type CallAsCurrentUser = ScopedClusterClient['callAsCurrentUser']; diff --git a/x-pack/plugins/snapshot_restore/test/fixtures/snapshot.ts b/x-pack/plugins/snapshot_restore/test/fixtures/snapshot.ts index d6a55579b322d..be0550d9c6b54 100644 --- a/x-pack/plugins/snapshot_restore/test/fixtures/snapshot.ts +++ b/x-pack/plugins/snapshot_restore/test/fixtures/snapshot.ts @@ -20,6 +20,7 @@ export const getSnapshot = ({ versionId: 8000099, version: '8.0.0', indices: new Array(totalIndices).fill('').map(getRandomString), + dataStreams: [], includeGlobalState: 1, state, startTime: '2019-05-23T06:25:15.896Z', From 872ed19e1f6fbf714fee72c371426dc72922a7e8 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 25 Jun 2020 18:20:04 +0200 Subject: [PATCH 17/43] First iteration that is ready for review Given the contraints on working with data streams and indices in policies at the moment the simplest implementation is to just include data streams with indices and have the user select them there for now. The way snapshotting behaviour is currently implemented relies entirely on what is specified inside of "indices", this is also where data streams must be placed. This unfortunately means that capture patterns defined in indices will capture entire data streams too. --- .../client_integration/policy_add.test.ts | 12 - .../common/lib/snapshot_serialization.ts | 14 +- .../snapshot_restore/common/types/indices.ts | 2 +- .../snapshot_restore/common/types/snapshot.ts | 1 - .../policy_form/steps/step_review.tsx | 18 +- .../fields/data_stream_badge.tsx | 18 ++ .../fields/data_streams_field.tsx | 237 ------------------ .../steps/step_settings/fields/index.ts | 1 - .../step_settings/fields/indices_field.tsx | 118 ++++++--- .../steps/step_settings/step_settings.tsx | 15 +- .../steps/step_logistics/step_logistics.tsx | 2 +- .../sections/policy_edit/policy_edit.tsx | 17 +- .../separate_data_streams_from_indices.ts | 36 --- .../services/validation/validate_policy.ts | 33 +-- .../server/routes/api/validate_schemas.ts | 1 - 15 files changed, 128 insertions(+), 397 deletions(-) create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx delete mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx delete mode 100644 x-pack/plugins/snapshot_restore/public/application/sections/policy_edit/separate_data_streams_from_indices.ts diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts index 79621fc2f1fc1..cc44acc9aa5c4 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts @@ -114,18 +114,6 @@ describe('', () => { expect(form.getErrorsMessages()).toEqual(['You must select at least one index.']); }); - test('should not require at least one index if a data stream is provided', async () => { - const { form, component } = testBed; - - await act(async () => { - // Toggle "All data streams" switch. Not all data streams are selected by default. - form.toggleEuiSwitch('allDataStreamsToggle', false); - await nextTick(); - component.update(); - }); - - expect(form.getErrorsMessages()).toEqual([]); - }); }); describe('retention (step 3)', () => { diff --git a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts index 562c083436b27..06bf7fbc0d967 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts @@ -129,22 +129,12 @@ export function deserializeSnapshotConfig(snapshotConfigEs: SnapshotConfigEs): S } export function serializeSnapshotConfig(snapshotConfig: SnapshotConfig): SnapshotConfigEs { - const { - indices, - dataStreams, - ignoreUnavailable, - includeGlobalState, - partial, - metadata, - } = snapshotConfig; + const { indices, ignoreUnavailable, includeGlobalState, partial, metadata } = snapshotConfig; const indicesArray = indicesToArray(indices); - // Even though data streams are not indices, we can treat the input the same way - // we treat input for the indices field because it gets concatenated to it. - const dataStreamsArray = indicesToArray(dataStreams); const snapshotConfigEs: SnapshotConfigEs = { - indices: indicesArray.concat(dataStreamsArray), + indices: indicesArray, ignore_unavailable: ignoreUnavailable, include_global_state: includeGlobalState, partial, diff --git a/x-pack/plugins/snapshot_restore/common/types/indices.ts b/x-pack/plugins/snapshot_restore/common/types/indices.ts index e6464dfe72da8..5e4f2b5fdc167 100644 --- a/x-pack/plugins/snapshot_restore/common/types/indices.ts +++ b/x-pack/plugins/snapshot_restore/common/types/indices.ts @@ -5,6 +5,6 @@ */ export interface PolicyIndicesResponse { - dataStreams: string[]; indices: string[]; + dataStreams: string[]; } diff --git a/x-pack/plugins/snapshot_restore/common/types/snapshot.ts b/x-pack/plugins/snapshot_restore/common/types/snapshot.ts index c6a58c713388d..1ff058e155385 100644 --- a/x-pack/plugins/snapshot_restore/common/types/snapshot.ts +++ b/x-pack/plugins/snapshot_restore/common/types/snapshot.ts @@ -5,7 +5,6 @@ */ export interface SnapshotConfig { indices?: string | string[]; - dataStreams?: string | string[]; ignoreUnavailable?: boolean; includeGlobalState?: boolean; partial?: boolean; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx index b8c5bab6a7ccf..a95e0515fef0f 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx @@ -22,7 +22,7 @@ import { import { serializePolicy } from '../../../../../common/lib'; import { useServices } from '../../../app_context'; import { StepProps } from './'; -import { CollapsibleIndicesList, CollapsibleDataStreamsList } from '../../collapsible_lists'; +import { CollapsibleIndicesList } from '../../collapsible_lists'; export const PolicyStepReview: React.FunctionComponent = ({ policy, @@ -30,9 +30,8 @@ export const PolicyStepReview: React.FunctionComponent = ({ }) => { const { i18n } = useServices(); const { name, snapshotName, schedule, repository, config, retention } = policy; - const { indices, includeGlobalState, ignoreUnavailable, partial, dataStreams } = config || { + const { indices, includeGlobalState, ignoreUnavailable, partial } = config || { indices: undefined, - dataStreams: undefined, includeGlobalState: undefined, ignoreUnavailable: undefined, partial: undefined, @@ -158,19 +157,6 @@ export const PolicyStepReview: React.FunctionComponent = ({ - - - - - - - - - - diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx new file mode 100644 index 0000000000000..e7d3f59bd567a --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx @@ -0,0 +1,18 @@ +/* + * 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 { EuiBadge } from '@elastic/eui'; + +export const DataStreamBadge: FunctionComponent = () => { + return ( + + {i18n.translate('xpack.snapshotRestore.policyForm.setSettings.dataStreamBadgeContent', { + defaultMessage: 'Data stream', + })} + + ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx deleted file mode 100644 index 4cd92c4763d41..0000000000000 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_streams_field.tsx +++ /dev/null @@ -1,237 +0,0 @@ -/* - * 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 React, { Fragment, FunctionComponent, useState } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { - EuiDescribedFormGroup, - EuiFlexGroup, - EuiFlexItem, - EuiFormRow, - EuiLink, - EuiPanel, - EuiSelectable, - EuiSelectableOption, - EuiSpacer, - EuiSwitch, - EuiTitle, - EuiToolTip, -} from '@elastic/eui'; - -import { SlmPolicyPayload } from '../../../../../../../common/types'; -import { PolicyValidation } from '../../../../../services/validation'; - -interface Props { - isManagedPolicy: boolean; - policy: SlmPolicyPayload; - dataStreams: string[]; - onUpdate: (arg: { dataStreams?: string[] | string }) => void; - errors: PolicyValidation['errors']; -} - -export const DataStreamsField: FunctionComponent = ({ - isManagedPolicy, - dataStreams, - policy, - onUpdate, - errors, -}) => { - const { config = {} } = policy; - - // No data streams are selected by default - const [isAllDataStreams, setIsAllDataStreams] = useState( - () => - Array.isArray(config.dataStreams) && - config.dataStreams.length > 0 && - config.dataStreams.every((d) => dataStreams.includes(d)) - ); - - const [dataStreamsSelection, setDataStreamsSelection] = useState( - isAllDataStreams - ? [...dataStreams] - : Array.isArray(config.dataStreams) - ? dataStreams.filter((d) => (config.dataStreams! as string[]).includes(d)) - : [] - ); - - // States for choosing all data streams, or a subset, including caching previously chosen subset list - const [dataStreamOptions, setDataStreamOptions] = useState(() => { - return dataStreams.map( - (dataStream): EuiSelectableOption => ({ - label: dataStream, - checked: - isAllDataStreams || - // If dataStreams is a string, we default to custom input mode, so we mark individual data streams - // as selected if user goes back to list mode - typeof config.dataStreams === 'string' || - (Array.isArray(config.dataStreams) && config.dataStreams.includes(dataStream)) - ? 'on' - : undefined, - }) - ); - }); - - const dataStreamsSwitch = ( - - } - checked={isAllDataStreams} - disabled={isManagedPolicy} - data-test-subj="allDataStreamsToggle" - onChange={(e) => { - const isChecked = e.target.checked; - setIsAllDataStreams(isChecked); - if (isChecked) { - onUpdate({ dataStreams: [...dataStreams] }); - } else { - onUpdate({ - dataStreams: [...(dataStreamsSelection || [])], - }); - } - }} - /> - ); - - return ( - -

- -

- - } - description={ - - } - fullWidth - > - - - {isManagedPolicy ? ( - - -

- } - > - {dataStreamsSwitch} -
- ) : ( - dataStreamsSwitch - )} - {isAllDataStreams ? null : ( - - - - - - - - } - helpText={ - 0 ? ( - { - // TODO: Change this to setDataStreamOptions() when https://github.com/elastic/eui/issues/2071 is fixed - dataStreamOptions.forEach((option: EuiSelectableOption) => { - option.checked = undefined; - }); - onUpdate({ dataStreams: [] }); - setDataStreamsSelection([]); - }} - > - - - ) : ( - { - // TODO: Change this to setDataStreamOptions() when https://github.com/elastic/eui/issues/2071 is fixed - dataStreamOptions.forEach((option: EuiSelectableOption) => { - option.checked = 'on'; - }); - onUpdate({ dataStreams: [...dataStreams] }); - setDataStreamsSelection([...dataStreams]); - }} - > - - - ), - }} - /> - } - isInvalid={Boolean(errors.dataStreams)} - error={errors.dataStreams} - > - { - { - const newSelectedDataStreams: string[] = []; - options.forEach(({ label, checked }) => { - if (checked === 'on') { - newSelectedDataStreams.push(label); - } - }); - setDataStreamOptions(options); - onUpdate({ dataStreams: newSelectedDataStreams }); - setDataStreamsSelection(newSelectedDataStreams); - }} - searchable - height={300} - > - {(list, search) => ( - - {search} - {list} - - )} - - } - - - )} -
-
-
- ); -}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts index 644b8be7818bf..f5c429cb65bbb 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts @@ -5,4 +5,3 @@ */ export { IndicesField } from './indices_field'; -export { DataStreamsField } from './data_streams_field'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx index 870946e0a2c3b..4710b48cf5b39 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx @@ -21,22 +21,27 @@ import { EuiSwitch, EuiTitle, EuiToolTip, + euiPaletteColorBlindBehindText, } from '@elastic/eui'; import { SlmPolicyPayload } from '../../../../../../../common/types'; import { useServices } from '../../../../../app_context'; import { PolicyValidation } from '../../../../../services/validation'; +import { DataStreamBadge } from './data_stream_badge'; + interface Props { isManagedPolicy: boolean; policy: SlmPolicyPayload; indices: string[]; + dataStreams: string[]; onUpdate: (arg: { indices?: string[] | string }) => void; errors: PolicyValidation['errors']; } export const IndicesField: FunctionComponent = ({ isManagedPolicy, + dataStreams, indices, policy, onUpdate, @@ -45,54 +50,77 @@ export const IndicesField: FunctionComponent = ({ const { i18n } = useServices(); const { config = {} } = policy; + const indicesAndDataStreams = indices.concat(dataStreams); + // We assume all indices if the config has no indices entry or if we receive an empty array const [isAllIndices, setIsAllIndices] = useState( !config.indices || (Array.isArray(config.indices) && config.indices.length === 0) ); + const [indicesSelection, setIndicesSelection] = useState(() => Array.isArray(config.indices) && !isAllIndices - ? indices.filter((i) => (config.indices! as string[]).includes(i)) - : [...indices] + ? indicesAndDataStreams.filter((i) => (config.indices! as string[]).includes(i)) + : [...indicesAndDataStreams] ); + const mapSelectionToIndicesOptions = (selection: string[]): EuiSelectableOption[] => { + return indices + .map( + (index): EuiSelectableOption => { + return { + label: index, + checked: + isAllIndices || + // If indices is a string, we default to custom input mode, so we mark individual indices + // as selected if user goes back to list mode + typeof config.indices === 'string' || + selection.includes(index) + ? 'on' + : undefined, + }; + } + ) + .concat( + dataStreams.map( + (dataStream): EuiSelectableOption => { + return { + label: dataStream, + append: , + checked: + isAllIndices || + // If indices is a string, we default to custom input mode, so we mark individual indices + // as selected if user goes back to list mode + typeof config.indices === 'string' || + selection.includes(dataStream) + ? 'on' + : undefined, + }; + } + ) + ); + }; + // States for choosing all indices, or a subset, including caching previously chosen subset list const [indicesOptions, setIndicesOptions] = useState(() => - indices.map( - (index): EuiSelectableOption => { - return { - label: index, - checked: - isAllIndices || - // If indices is a string, we default to custom input mode, so we mark individual indices - // as selected if user goes back to list mode - typeof config.indices === 'string' || - indicesSelection.includes(index) - ? 'on' - : undefined, - }; - } - ) + mapSelectionToIndicesOptions(indicesSelection) ); // State for using selectable indices list or custom patterns // Users with more than 100 indices will probably want to use an index pattern to select // them instead, so we'll default to showing them the index pattern input. Also show the custom // list if we have no exact matches in the configured array to some existing index. - const [selectIndicesMode, setSelectIndicesMode] = useState<'list' | 'custom'>(() => - typeof config.indices === 'string' || - (Array.isArray(config.indices) && - (config.indices.length > 100 || !config.indices.every((c) => indices.some((i) => i === c)))) + const [selectIndicesMode, setSelectIndicesMode] = useState<'list' | 'custom'>(() => { + return typeof config.indices === 'string' || + (Array.isArray(config.indices) && + (config.indices.length > 100 || + !config.indices.every((c) => indicesAndDataStreams.some((i) => i === c)))) ? 'custom' - : 'list' - ); + : 'list'; + }); // State for custom patterns const [indexPatterns, setIndexPatterns] = useState(() => - typeof config.indices === 'string' - ? (config.indices as string).split(',') - : Array.isArray(config.indices) - ? config.indices - : [] + typeof config.indices === 'string' ? (config.indices as string).split(',') : [] ); const indicesSwitch = ( @@ -100,7 +128,7 @@ export const IndicesField: FunctionComponent = ({ label={ } checked={isAllIndices} @@ -110,6 +138,8 @@ export const IndicesField: FunctionComponent = ({ const isChecked = e.target.checked; setIsAllIndices(isChecked); if (isChecked) { + setIndicesSelection(indicesAndDataStreams); + setIndicesOptions(mapSelectionToIndicesOptions(indicesAndDataStreams)); onUpdate({ indices: undefined }); } else { onUpdate({ @@ -130,7 +160,7 @@ export const IndicesField: FunctionComponent = ({

@@ -138,7 +168,7 @@ export const IndicesField: FunctionComponent = ({ description={ } fullWidth @@ -291,7 +321,31 @@ export const IndicesField: FunctionComponent = ({ ) : ( ({ label: index }))} + options={indices + .map((index) => ({ label: index, value: { isDataStream: false } })) + .concat( + dataStreams.map((dataStream) => ({ + label: dataStream, + value: { isDataStream: true }, + })) + )} + renderOption={({ label, value }) => { + if (value?.isDataStream) { + return ( + + {label} + + + + + ); + } + return label; + }} placeholder={i18n.translate( 'xpack.snapshotRestore.policyForm.stepSettings.indicesPatternPlaceholder', { diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx index 66072ce314b9f..909af62b7a2e7 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx @@ -20,12 +20,12 @@ import { SlmPolicyPayload } from '../../../../../../common/types'; import { documentationLinksService } from '../../../../services/documentation'; import { StepProps } from '../'; -import { IndicesField, DataStreamsField } from './fields'; +import { IndicesField } from './fields'; export const PolicyStepSettings: React.FunctionComponent = ({ policy, - dataStreams, indices, + dataStreams, updatePolicy, errors, }) => { @@ -133,7 +133,7 @@ export const PolicyStepSettings: React.FunctionComponent = ({ description={ } fullWidth @@ -190,17 +190,10 @@ export const PolicyStepSettings: React.FunctionComponent = ({ - - diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index b7ef0526d9336..cfe31e14b3c23 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -526,7 +526,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = } fullWidth diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/policy_edit/policy_edit.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/policy_edit/policy_edit.tsx index 92af6b46ccf6b..915b1cbef1233 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/policy_edit/policy_edit.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/policy_edit/policy_edit.tsx @@ -16,7 +16,6 @@ import { BASE_PATH } from '../../constants'; import { useServices } from '../../app_context'; import { breadcrumbService, docTitleService } from '../../services/navigation'; import { editPolicy, useLoadPolicy, useLoadIndices } from '../../services/http'; -import { separateDataStreamsFromIndices } from './separate_data_streams_from_indices'; interface MatchParams { name: string; @@ -66,20 +65,10 @@ export const PolicyEdit: React.FunctionComponent { - if (policyData && policyData.policy && indicesData) { - const indicesAndDataStreams = separateDataStreamsFromIndices( - indicesData, - policyData.policy.config?.indices ?? [] - ); - setPolicy({ - ...policyData.policy, - config: { - ...policyData.policy.config, - ...indicesAndDataStreams, - }, - }); + if (policyData && policyData.policy) { + setPolicy(policyData.policy); } - }, [policyData, indicesData]); + }, [policyData]); // Saving policy states const [isSaving, setIsSaving] = useState(false); diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/policy_edit/separate_data_streams_from_indices.ts b/x-pack/plugins/snapshot_restore/public/application/sections/policy_edit/separate_data_streams_from_indices.ts deleted file mode 100644 index f30cb266d15c4..0000000000000 --- a/x-pack/plugins/snapshot_restore/public/application/sections/policy_edit/separate_data_streams_from_indices.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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 { PolicyIndicesResponse } from '../../../../common/types'; -import { indicesToArray } from '../../../../common/lib'; - -interface Result { - dataStreams: string[]; - indices: string[]; -} - -/** - * This function is used temporarily until we have a resolution to - * https://github.com/elastic/elasticsearch/issues/58474 from ES side. - */ -export const separateDataStreamsFromIndices = ( - { dataStreams, indices }: PolicyIndicesResponse, - configuredPatterns: string[] | string | undefined -): Result => { - const configuredPatternsArray = indicesToArray(configuredPatterns); - const result: Result = { - dataStreams: [], - indices: [], - }; - for (const indexOrDataStreamPattern of configuredPatternsArray) { - if (dataStreams.some((ds) => ds === indexOrDataStreamPattern)) { - result.dataStreams.push(indexOrDataStreamPattern); - } else { - result.indices.push(indexOrDataStreamPattern); - } - } - return result; -}; diff --git a/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_policy.ts b/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_policy.ts index 112522a53553f..75aba5953231c 100644 --- a/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_policy.ts +++ b/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_policy.ts @@ -48,6 +48,7 @@ export const validatePolicy = ( snapshotName: [], schedule: [], repository: [], + dataStreams: [], indices: [], expireAfterValue: [], minCount: [], @@ -95,32 +96,20 @@ export const validatePolicy = ( ); } - const hasDataStreams = () => { - return ( - config && - ((typeof config.dataStreams === 'string' && config.dataStreams.trim().length > 0) || - (Array.isArray(config.dataStreams) && config.dataStreams.length > 0)) - ); - }; - if (config && typeof config.indices === 'string' && config.indices.trim().length === 0) { - if (!hasDataStreams()) { - validation.errors.indices.push( - i18n.translate('xpack.snapshotRestore.policyValidation.indexPatternRequiredErrorMessage', { - defaultMessage: 'At least one index pattern is required.', - }) - ); - } + validation.errors.indices.push( + i18n.translate('xpack.snapshotRestore.policyValidation.indexPatternRequiredErrorMessage', { + defaultMessage: 'At least one index pattern is required.', + }) + ); } if (config && Array.isArray(config.indices) && config.indices.length === 0) { - if (!hasDataStreams()) { - validation.errors.indices.push( - i18n.translate('xpack.snapshotRestore.policyValidation.indicesRequiredErrorMessage', { - defaultMessage: 'You must select at least one index.', - }) - ); - } + validation.errors.indices.push( + i18n.translate('xpack.snapshotRestore.policyValidation.indicesRequiredErrorMessage', { + defaultMessage: 'You must select at least one index.', + }) + ); } if ( diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts b/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts index 953f61b4ff128..e5df0ec33db0b 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/validate_schemas.ts @@ -10,7 +10,6 @@ export const nameParameterSchema = schema.object({ }); const snapshotConfigSchema = schema.object({ - dataStreams: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), indices: schema.maybe(schema.oneOf([schema.string(), schema.arrayOf(schema.string())])), ignoreUnavailable: schema.maybe(schema.boolean()), includeGlobalState: schema.maybe(schema.boolean()), From 904fa39449a522363eae1f5fd62393c67204478e Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 25 Jun 2020 18:22:32 +0200 Subject: [PATCH 18/43] delete unused import --- .../policy_form/steps/step_settings/fields/indices_field.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx index 4710b48cf5b39..0a408011a52c4 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx @@ -21,7 +21,6 @@ import { EuiSwitch, EuiTitle, EuiToolTip, - euiPaletteColorBlindBehindText, } from '@elastic/eui'; import { SlmPolicyPayload } from '../../../../../../../common/types'; From a28fa5c602eea6049f26097f31980bcbf19b96a9 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Fri, 26 Jun 2020 15:19:31 +0200 Subject: [PATCH 19/43] fix type issue in tests --- .../__jest__/client_integration/helpers/setup_environment.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx index e26a9e79980f6..80b990d141974 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx @@ -64,7 +64,7 @@ export const setupEnvironment = () => { }; }; -window.Worker = function Worker() { +(window as any).Worker = function Worker() { this.postMessage = () => {}; this.terminate = () => {}; }; From 14fef2242228c49499a984694c03e89899af19ac Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Fri, 26 Jun 2020 15:54:20 +0200 Subject: [PATCH 20/43] added logic for rendering out previous selection as custom pattern --- .../steps/step_settings/fields/indices_field.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx index 0a408011a52c4..eed6e2d5ea6de 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx @@ -119,7 +119,11 @@ export const IndicesField: FunctionComponent = ({ // State for custom patterns const [indexPatterns, setIndexPatterns] = useState(() => - typeof config.indices === 'string' ? (config.indices as string).split(',') : [] + typeof config.indices === 'string' + ? (config.indices as string).split(',') + : Array.isArray(config.indices) + ? config.indices + : [] ); const indicesSwitch = ( @@ -202,7 +206,7 @@ export const IndicesField: FunctionComponent = ({ From ce30c6c738be7cdacf63bee5643b25451f374772 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Mon, 29 Jun 2020 11:40:43 +0200 Subject: [PATCH 21/43] refactor indices fields to make component smaller --- .../{ => components}/data_stream_badge.tsx | 0 .../step_settings/fields/components/index.ts | 7 ++ .../steps/step_settings/fields/index.ts | 2 +- .../helpers.tsx | 68 +++++++++++++++ .../indices_and_data_streams_field/index.ts | 7 ++ .../indices_and_data_streams_field.tsx} | 87 +++++++------------ .../steps/step_settings/step_settings.tsx | 4 +- 7 files changed, 116 insertions(+), 59 deletions(-) rename x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/{ => components}/data_stream_badge.tsx (100%) create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/components/index.ts create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/index.ts rename x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/{indices_field.tsx => indices_and_data_streams_field/indices_and_data_streams_field.tsx} (85%) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/components/data_stream_badge.tsx similarity index 100% rename from x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/data_stream_badge.tsx rename to x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/components/data_stream_badge.tsx diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/components/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/components/index.ts new file mode 100644 index 0000000000000..4b38ea6b2a34a --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/components/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { DataStreamBadge } from './data_stream_badge'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts index f5c429cb65bbb..e0d632a58e4e1 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/index.ts @@ -4,4 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { IndicesField } from './indices_field'; +export { IndicesAndDataStreamsField } from './indices_and_data_streams_field'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx new file mode 100644 index 0000000000000..423ff6c0e2847 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx @@ -0,0 +1,68 @@ +/* + * 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 React from 'react'; +import { EuiSelectableOption } from '@elastic/eui'; +import { DataStreamBadge } from '../components'; + +export const mapSelectionToIndicesOptions = ({ + allSelected, + selection, + dataStreams, + indices, +}: { + allSelected: boolean; + selection: string[]; + dataStreams: string[]; + indices: string[]; +}): EuiSelectableOption[] => { + return indices + .map( + (index): EuiSelectableOption => { + return { + label: index, + checked: allSelected || selection.includes(index) ? 'on' : undefined, + }; + } + ) + .concat( + dataStreams.map( + (dataStream): EuiSelectableOption => { + return { + label: dataStream, + append: , + checked: allSelected || selection.includes(dataStream) ? 'on' : undefined, + }; + } + ) + ); +}; + +/** + * @remark + * Users with more than 100 indices will probably want to use an index pattern to select + * them instead, so we'll default to showing them the index pattern input. Also show the custom + * list if we have no exact matches in the configured array to some existing index. + */ +export const determineListMode = ({ + configuredIndices, + indices, + dataStreams, +}: { + configuredIndices: string | string[] | undefined; + indices: string[]; + dataStreams: string[]; +}): 'custom' | 'list' => { + const indicesAndDataStreams = indices.concat(dataStreams); + return typeof configuredIndices === 'string' || + (Array.isArray(configuredIndices) && + (indices.length > 100 || + // If not every past configured index maps to an existing index or data stream + // we also show the custom list + !configuredIndices.every((c) => indicesAndDataStreams.some((i) => i === c)))) + ? 'custom' + : 'list'; +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/index.ts new file mode 100644 index 0000000000000..e0d632a58e4e1 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/index.ts @@ -0,0 +1,7 @@ +/* + * 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. + */ + +export { IndicesAndDataStreamsField } from './indices_and_data_streams_field'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx similarity index 85% rename from x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx rename to x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx index eed6e2d5ea6de..c6eadd2e5ce7a 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx @@ -23,11 +23,13 @@ import { EuiToolTip, } from '@elastic/eui'; -import { SlmPolicyPayload } from '../../../../../../../common/types'; -import { useServices } from '../../../../../app_context'; -import { PolicyValidation } from '../../../../../services/validation'; +import { SlmPolicyPayload } from '../../../../../../../../common/types'; +import { useServices } from '../../../../../../app_context'; +import { PolicyValidation } from '../../../../../../services/validation'; -import { DataStreamBadge } from './data_stream_badge'; +import { DataStreamBadge } from '../components'; + +import { mapSelectionToIndicesOptions, determineListMode } from './helpers'; interface Props { isManagedPolicy: boolean; @@ -38,7 +40,12 @@ interface Props { errors: PolicyValidation['errors']; } -export const IndicesField: FunctionComponent = ({ +/** + * In future we may be able to split data streams to it's own field, but for now + * they share an array "indices" in the snapshot lifecycle policy config. See + * this github issue for progress: https://github.com/elastic/elasticsearch/issues/58474 + */ +export const IndicesAndDataStreamsField: FunctionComponent = ({ isManagedPolicy, dataStreams, indices, @@ -62,66 +69,26 @@ export const IndicesField: FunctionComponent = ({ : [...indicesAndDataStreams] ); - const mapSelectionToIndicesOptions = (selection: string[]): EuiSelectableOption[] => { - return indices - .map( - (index): EuiSelectableOption => { - return { - label: index, - checked: - isAllIndices || - // If indices is a string, we default to custom input mode, so we mark individual indices - // as selected if user goes back to list mode - typeof config.indices === 'string' || - selection.includes(index) - ? 'on' - : undefined, - }; - } - ) - .concat( - dataStreams.map( - (dataStream): EuiSelectableOption => { - return { - label: dataStream, - append: , - checked: - isAllIndices || - // If indices is a string, we default to custom input mode, so we mark individual indices - // as selected if user goes back to list mode - typeof config.indices === 'string' || - selection.includes(dataStream) - ? 'on' - : undefined, - }; - } - ) - ); - }; - // States for choosing all indices, or a subset, including caching previously chosen subset list const [indicesOptions, setIndicesOptions] = useState(() => - mapSelectionToIndicesOptions(indicesSelection) + mapSelectionToIndicesOptions({ + selection: indicesSelection, + dataStreams, + indices, + allSelected: isAllIndices || typeof config.indices === 'string', + }) ); // State for using selectable indices list or custom patterns - // Users with more than 100 indices will probably want to use an index pattern to select - // them instead, so we'll default to showing them the index pattern input. Also show the custom - // list if we have no exact matches in the configured array to some existing index. - const [selectIndicesMode, setSelectIndicesMode] = useState<'list' | 'custom'>(() => { - return typeof config.indices === 'string' || - (Array.isArray(config.indices) && - (config.indices.length > 100 || - !config.indices.every((c) => indicesAndDataStreams.some((i) => i === c)))) - ? 'custom' - : 'list'; - }); + const [selectIndicesMode, setSelectIndicesMode] = useState<'list' | 'custom'>(() => + determineListMode({ configuredIndices: config.indices, dataStreams, indices }) + ); // State for custom patterns const [indexPatterns, setIndexPatterns] = useState(() => typeof config.indices === 'string' ? (config.indices as string).split(',') - : Array.isArray(config.indices) + : Array.isArray(config.indices) && config.indices ? config.indices : [] ); @@ -142,7 +109,14 @@ export const IndicesField: FunctionComponent = ({ setIsAllIndices(isChecked); if (isChecked) { setIndicesSelection(indicesAndDataStreams); - setIndicesOptions(mapSelectionToIndicesOptions(indicesAndDataStreams)); + setIndicesOptions( + mapSelectionToIndicesOptions({ + allSelected: isAllIndices || typeof config.indices === 'string', + dataStreams, + indices, + selection: indicesSelection, + }) + ); onUpdate({ indices: undefined }); } else { onUpdate({ @@ -300,6 +274,7 @@ export const IndicesField: FunctionComponent = ({ {selectIndicesMode === 'list' ? ( { const newSelectedIndices: string[] = []; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx index 909af62b7a2e7..4f21f2855b4a7 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx @@ -20,7 +20,7 @@ import { SlmPolicyPayload } from '../../../../../../common/types'; import { documentationLinksService } from '../../../../services/documentation'; import { StepProps } from '../'; -import { IndicesField } from './fields'; +import { IndicesAndDataStreamsField } from './fields'; export const PolicyStepSettings: React.FunctionComponent = ({ policy, @@ -189,7 +189,7 @@ export const PolicyStepSettings: React.FunctionComponent = ({ - Date: Mon, 29 Jun 2020 12:23:33 +0200 Subject: [PATCH 22/43] added CIT for data streams badge --- .../client_integration/helpers/index.ts | 2 +- .../client_integration/helpers/mocks.tsx | 18 ++++++++++++++++ ...policy_add.test.ts => policy_add.test.tsx} | 21 +++++++++++++++++-- 3 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/mocks.tsx rename x-pack/plugins/snapshot_restore/__jest__/client_integration/{policy_add.test.ts => policy_add.test.tsx} (93%) diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/index.ts index 2f7b75dfba57e..e8efe94396b2a 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/index.ts @@ -3,7 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - +import './mocks'; import { setup as homeSetup } from './home.helpers'; import { setup as repositoryAddSetup } from './repository_add.helpers'; import { setup as repositoryEditSetup } from './repository_edit.helpers'; diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/mocks.tsx b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/mocks.tsx new file mode 100644 index 0000000000000..f3d03574cd10a --- /dev/null +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/mocks.tsx @@ -0,0 +1,18 @@ +/* + * 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 React from 'react'; + +jest.mock('react-virtualized', () => { + const original = jest.requireActual('react-virtualized'); + + return { + ...original, + AutoSizer: ({ children }: { children: any }) => ( +
{children({ height: 500, width: 500 })}
+ ), + }; +}); diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.tsx similarity index 93% rename from x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts rename to x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.tsx index cc44acc9aa5c4..f7cbd266f956e 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.tsx @@ -3,11 +3,15 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ + +// import helpers first, this also sets up the mocks +import { setupEnvironment, pageHelpers, nextTick, getRandomString } from './helpers'; + +import React from 'react'; import { act } from 'react-dom/test-utils'; import * as fixtures from '../../test/fixtures'; -import { setupEnvironment, pageHelpers, nextTick, getRandomString } from './helpers'; import { PolicyFormTestBed } from './helpers/policy_form.helpers'; import { DEFAULT_POLICY_SCHEDULE } from '../../public/application/constants'; @@ -39,7 +43,7 @@ describe('', () => { httpRequestsMockHelpers.setLoadRepositoriesResponse({ repositories: [repository] }); httpRequestsMockHelpers.setLoadIndicesResponse({ indices: ['my_index'], - dataStreams: ['my_data_stream'], + dataStreams: ['my_data_stream', 'my_other_data_stream'], }); testBed = await setup(); @@ -114,6 +118,19 @@ describe('', () => { expect(form.getErrorsMessages()).toEqual(['You must select at least one index.']); }); + + test('should correctly indicate data streams with a badge', async () => { + const { find, component, form } = testBed; + + await act(async () => { + // Toggle "All indices" switch + form.toggleEuiSwitch('allIndicesToggle', false); + await nextTick(); + }); + component.update(); + + expect(find('dataStreamBadge').length).toBe(2); + }); }); describe('retention (step 3)', () => { From 7f0b878f37c57e1e80e515df5191e161546cbfb7 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Mon, 29 Jun 2020 16:29:34 +0200 Subject: [PATCH 23/43] Data streams > indices --- .../helpers.tsx | 37 ++++++++++++------- .../indices_and_data_streams_field.tsx | 24 +++++++----- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx index 423ff6c0e2847..ecdf2b6ab8d2a 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx @@ -8,6 +8,16 @@ import React from 'react'; import { EuiSelectableOption } from '@elastic/eui'; import { DataStreamBadge } from '../components'; +export const orderDataStreamsAndIndices = ({ + dataStreams, + indices, +}: { + indices: D[]; + dataStreams: D[]; +}) => { + return dataStreams.concat(indices); +}; + export const mapSelectionToIndicesOptions = ({ allSelected, selection, @@ -19,26 +29,25 @@ export const mapSelectionToIndicesOptions = ({ dataStreams: string[]; indices: string[]; }): EuiSelectableOption[] => { - return indices - .map( + return orderDataStreamsAndIndices({ + dataStreams: dataStreams.map( + (dataStream): EuiSelectableOption => { + return { + label: dataStream, + append: , + checked: allSelected || selection.includes(dataStream) ? 'on' : undefined, + }; + } + ), + indices: indices.map( (index): EuiSelectableOption => { return { label: index, checked: allSelected || selection.includes(index) ? 'on' : undefined, }; } - ) - .concat( - dataStreams.map( - (dataStream): EuiSelectableOption => { - return { - label: dataStream, - append: , - checked: allSelected || selection.includes(dataStream) ? 'on' : undefined, - }; - } - ) - ); + ), + }); }; /** diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx index c6eadd2e5ce7a..23ed99645353c 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx @@ -29,7 +29,11 @@ import { PolicyValidation } from '../../../../../../services/validation'; import { DataStreamBadge } from '../components'; -import { mapSelectionToIndicesOptions, determineListMode } from './helpers'; +import { + mapSelectionToIndicesOptions, + determineListMode, + orderDataStreamsAndIndices, +} from './helpers'; interface Props { isManagedPolicy: boolean; @@ -299,14 +303,16 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({
) : ( ({ label: index, value: { isDataStream: false } })) - .concat( - dataStreams.map((dataStream) => ({ - label: dataStream, - value: { isDataStream: true }, - })) - )} + options={orderDataStreamsAndIndices({ + indices: indices.map((index) => ({ + label: index, + value: { isDataStream: false }, + })), + dataStreams: dataStreams.map((dataStream) => ({ + label: dataStream, + value: { isDataStream: true }, + })), + })} renderOption={({ label, value }) => { if (value?.isDataStream) { return ( From 856c39a495a5a8c20c890f3dbe4f47bd756aa40c Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Mon, 29 Jun 2020 16:35:16 +0200 Subject: [PATCH 24/43] updates to relevant pieces of copy --- .../steps/step_logistics/data_stream_badge.tsx | 3 +-- .../steps/step_logistics/step_logistics.tsx | 14 +++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_stream_badge.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_stream_badge.tsx index 042d9d6df2e6d..6af4f2b1e95b1 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_stream_badge.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_stream_badge.tsx @@ -14,8 +14,7 @@ export const DataStreamBadge: FunctionComponent = () => { content={i18n.translate( 'xpack.snapshotRestore.restoreForm.stepLogistics.dataStreamBadgeToolTip', { - defaultMessage: - 'This is a backing index. Excluding this index when restoring may cause unintended data loss for a data stream.', + defaultMessage: 'This is a backing index for a data stream.', } )} > diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index cfe31e14b3c23..4b9c556be7ec3 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -135,7 +135,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent =

@@ -143,7 +143,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = description={ } @@ -155,7 +155,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = label={ } checked={isAllIndices} @@ -185,7 +185,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = @@ -219,7 +219,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = >
@@ -230,7 +230,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = selectIndicesMode === 'list' ? ( = } fullWidth From ae5863ba76b1d77792c03d3cc3bc65b69ff694d8 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Mon, 29 Jun 2020 16:38:22 +0200 Subject: [PATCH 25/43] more copy updates --- .../steps/step_logistics/step_logistics.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index 4b9c556be7ec3..656983e92c226 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -368,7 +368,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent =

@@ -376,7 +376,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = description={ } fullWidth @@ -387,7 +387,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = label={ } checked={isRenamingIndices} @@ -430,7 +430,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = > { setCachedRestoreSettings({ ...cachedRestoreSettings, @@ -456,7 +456,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = > { setCachedRestoreSettings({ ...cachedRestoreSettings, From d98e6f7fc8f86cef9ff455d0fe7c52cc3652a20c Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 30 Jun 2020 14:18:43 +0200 Subject: [PATCH 26/43] fix types and remove unused import --- .../__jest__/client_integration/helpers/policy_form.helpers.ts | 1 + .../__jest__/client_integration/policy_add.test.tsx | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/policy_form.helpers.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/policy_form.helpers.ts index 70f3cdafc427a..a3ab829ab642c 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/policy_form.helpers.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/policy_form.helpers.ts @@ -55,4 +55,5 @@ export type PolicyFormTestSubjects = | 'selectIndicesLink' | 'showAdvancedCronLink' | 'snapshotNameInput' + | 'dataStreamBadge' | 'submitButton'; diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.tsx b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.tsx index f7cbd266f956e..3164af519ae10 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.tsx +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.tsx @@ -7,7 +7,6 @@ // import helpers first, this also sets up the mocks import { setupEnvironment, pageHelpers, nextTick, getRandomString } from './helpers'; -import React from 'react'; import { act } from 'react-dom/test-utils'; import * as fixtures from '../../test/fixtures'; From b2e6b905b62219e4c6c1dd068f9c14032b7cfb3f Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 30 Jun 2020 15:19:41 +0200 Subject: [PATCH 27/43] removed backing indices from restore view --- .../step_settings/fields/components/index.ts | 7 -- .../helpers.tsx | 12 +- .../indices_and_data_streams_field.tsx | 8 +- .../step_logistics/data_stream_badge.tsx | 29 ----- .../steps/step_logistics/step_logistics.tsx | 119 ++++++++++++------ .../data_stream_badge.tsx | 0 6 files changed, 86 insertions(+), 89 deletions(-) delete mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/components/index.ts delete mode 100644 x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_stream_badge.tsx rename x-pack/plugins/snapshot_restore/public/application/components/{policy_form/steps/step_settings/fields/components => shared}/data_stream_badge.tsx (100%) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/components/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/components/index.ts deleted file mode 100644 index 4b38ea6b2a34a..0000000000000 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/components/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -/* - * 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. - */ - -export { DataStreamBadge } from './data_stream_badge'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx index ecdf2b6ab8d2a..465aa20f3fd88 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx @@ -6,17 +6,7 @@ import React from 'react'; import { EuiSelectableOption } from '@elastic/eui'; -import { DataStreamBadge } from '../components'; - -export const orderDataStreamsAndIndices = ({ - dataStreams, - indices, -}: { - indices: D[]; - dataStreams: D[]; -}) => { - return dataStreams.concat(indices); -}; +import { DataStreamBadge, orderDataStreamsAndIndices } from '../../../../../shared'; export const mapSelectionToIndicesOptions = ({ allSelected, diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx index 23ed99645353c..3eb7e11e1f407 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx @@ -27,13 +27,9 @@ import { SlmPolicyPayload } from '../../../../../../../../common/types'; import { useServices } from '../../../../../../app_context'; import { PolicyValidation } from '../../../../../../services/validation'; -import { DataStreamBadge } from '../components'; +import { orderDataStreamsAndIndices, DataStreamBadge } from '../../../../../shared'; -import { - mapSelectionToIndicesOptions, - determineListMode, - orderDataStreamsAndIndices, -} from './helpers'; +import { mapSelectionToIndicesOptions, determineListMode } from './helpers'; interface Props { isManagedPolicy: boolean; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_stream_badge.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_stream_badge.tsx deleted file mode 100644 index 6af4f2b1e95b1..0000000000000 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_stream_badge.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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 { EuiBadge, EuiToolTip } from '@elastic/eui'; - -export const DataStreamBadge: FunctionComponent = () => { - return ( - - - {i18n.translate( - 'xpack.snapshotRestore.restoreForm.stepLogistics.backingIndexBadgeContent', - { defaultMessage: 'Backing index' } - )} - - - ); -}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index 656983e92c226..0b740734dcc46 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -29,7 +29,7 @@ import { documentationLinksService } from '../../../../services/documentation'; import { useServices } from '../../../../app_context'; -import { DataStreamBadge } from './data_stream_badge'; +import { orderDataStreamsAndIndices, DataStreamBadge } from '../../../shared'; import { StepProps } from '../index'; @@ -41,10 +41,30 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = }) => { const { i18n } = useServices(); const { - indices: snapshotIndices, + indices: unfilteredSnapshotIndices, + dataStreams: snapshotDataStreams, includeGlobalState: snapshotIncludeGlobalState, } = snapshotDetails; + const snapshotIndices = unfilteredSnapshotIndices.filter( + (index) => !isDataStreamBackingIndex(index) + ); + const snapshotIndicesAndDataStreams = snapshotIndices.concat(snapshotDataStreams); + + const comboBoxOptions = orderDataStreamsAndIndices<{ + label: string; + value: { isDataStream: boolean; name: string }; + }>({ + dataStreams: snapshotDataStreams.map((dataStream) => ({ + label: dataStream, + value: { isDataStream: true, name: dataStream }, + })), + indices: snapshotIndices.map((index) => ({ + label: index, + value: { isDataStream: false, name: index }, + })), + }); + const { indices: restoreIndices, renamePattern, @@ -54,29 +74,50 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = } = restoreSettings; // States for choosing all indices, or a subset, including caching previously chosen subset list - const [isAllIndices, setIsAllIndices] = useState(!Boolean(restoreIndices)); - const [indicesOptions, setIndicesOptions] = useState( - snapshotIndices.map( - (index): EuiSelectableOption => ({ - label: index, - append: isDataStreamBackingIndex(index) ? : undefined, - checked: - isAllIndices || - // If indices is a string, we default to custom input mode, so we mark individual indices - // as selected if user goes back to list mode - typeof restoreIndices === 'string' || - (Array.isArray(restoreIndices) && restoreIndices.includes(index)) - ? 'on' - : undefined, - }) - ) + const [isAllIndicesAndDataStreams, setIsAllIndicesAndDataStreams] = useState( + !Boolean(restoreIndices) + ); + const [indicesAndDataStreamsOptions, setIndicesAndDataStreamsOptions] = useState< + EuiSelectableOption[] + >(() => + orderDataStreamsAndIndices({ + dataStreams: snapshotDataStreams.map( + (dataStream): EuiSelectableOption => ({ + label: dataStream, + append: , + checked: + isAllIndicesAndDataStreams || + // If indices is a string, we default to custom input mode, so we mark individual indices + // as selected if user goes back to list mode + typeof restoreIndices === 'string' || + (Array.isArray(restoreIndices) && restoreIndices.includes(dataStream)) + ? 'on' + : undefined, + }) + ), + indices: snapshotIndices.map( + (index): EuiSelectableOption => ({ + label: index, + checked: + isAllIndicesAndDataStreams || + // If indices is a string, we default to custom input mode, so we mark individual indices + // as selected if user goes back to list mode + typeof restoreIndices === 'string' || + (Array.isArray(restoreIndices) && restoreIndices.includes(index)) + ? 'on' + : undefined, + }) + ), + }) ); // State for using selectable indices list or custom patterns // Users with more than 100 indices will probably want to use an index pattern to select // them instead, so we'll default to showing them the index pattern input. const [selectIndicesMode, setSelectIndicesMode] = useState<'list' | 'custom'>( - typeof restoreIndices === 'string' || snapshotIndices.length > 100 ? 'custom' : 'list' + typeof restoreIndices === 'string' || snapshotIndicesAndDataStreams.length > 100 + ? 'custom' + : 'list' ); // State for custom patterns @@ -91,7 +132,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = // Caching state for togglable settings const [cachedRestoreSettings, setCachedRestoreSettings] = useState({ - indices: [...snapshotIndices], + indices: [...snapshotIndicesAndDataStreams], renamePattern: '', renameReplacement: '', }); @@ -158,10 +199,10 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = defaultMessage="All indices and data streams, including system indices" /> } - checked={isAllIndices} + checked={isAllIndicesAndDataStreams} onChange={(e) => { const isChecked = e.target.checked; - setIsAllIndices(isChecked); + setIsAllIndicesAndDataStreams(isChecked); if (isChecked) { updateRestoreSettings({ indices: undefined }); } else { @@ -174,7 +215,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = } }} /> - {isAllIndices ? null : ( + {isAllIndicesAndDataStreams ? null : ( = { // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed - indicesOptions.forEach((option: EuiSelectableOption) => { - option.checked = undefined; - }); + indicesAndDataStreamsOptions.forEach( + (option: EuiSelectableOption) => { + option.checked = undefined; + } + ); updateRestoreSettings({ indices: [] }); setCachedRestoreSettings({ ...cachedRestoreSettings, @@ -257,13 +300,17 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = { // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed - indicesOptions.forEach((option: EuiSelectableOption) => { - option.checked = 'on'; + indicesAndDataStreamsOptions.forEach( + (option: EuiSelectableOption) => { + option.checked = 'on'; + } + ); + updateRestoreSettings({ + indices: [...snapshotIndicesAndDataStreams], }); - updateRestoreSettings({ indices: [...snapshotIndices] }); setCachedRestoreSettings({ ...cachedRestoreSettings, - indices: [...snapshotIndices], + indices: [...snapshotIndicesAndDataStreams], }); }} > @@ -283,7 +330,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = {selectIndicesMode === 'list' ? ( { const newSelectedIndices: string[] = []; options.forEach(({ label, checked }) => { @@ -291,7 +338,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = newSelectedIndices.push(label); } }); - setIndicesOptions(options); + setIndicesAndDataStreamsOptions(options); updateRestoreSettings({ indices: [...newSelectedIndices] }); setCachedRestoreSettings({ ...cachedRestoreSettings, @@ -310,22 +357,22 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = ) : ( ({ label: index, value: index }))} + options={comboBoxOptions} renderOption={({ value }) => { - return isDataStreamBackingIndex(value!) ? ( + return value?.isDataStream ? ( - {value!} + {value.name} ) : ( - value! + value?.name ); }} placeholder={i18n.translate( diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/components/data_stream_badge.tsx b/x-pack/plugins/snapshot_restore/public/application/components/shared/data_stream_badge.tsx similarity index 100% rename from x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/components/data_stream_badge.tsx rename to x-pack/plugins/snapshot_restore/public/application/components/shared/data_stream_badge.tsx From 49c2857b0424d0960456e7d806d7cdb90620007c Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 30 Jun 2020 15:51:03 +0200 Subject: [PATCH 28/43] Added data stream restore warning message --- .../data_streams_global_state_call_out.tsx | 53 +++++++++++++++++++ .../steps/step_logistics/step_logistics.tsx | 9 +++- .../application/components/shared/helpers.ts | 15 ++++++ .../application/components/shared/index.ts | 9 ++++ .../documentation/documentation_links.ts | 4 ++ 5 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/shared/helpers.ts create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/shared/index.ts diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx new file mode 100644 index 0000000000000..239d1413b27b7 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx @@ -0,0 +1,53 @@ +/* + * 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 { FormattedMessage } from '@kbn/i18n/react'; +import React, { FunctionComponent } from 'react'; +import { EuiCallOut, EuiLink } from '@elastic/eui'; + +import { documentationLinksService } from '../../../../services/documentation'; + +const i18nTexts = { + callout: { + title: (count: number) => + i18n.translate('xpack.snapshotRestore.restoreForm.dataStreamsWarningCallOut.title', { + defaultMessage: 'Data {count, plural, one {stream} other {streams}} found in this snapshot', + values: { count }, + }), + body: () => ( + + {i18n.translate( + 'xpack.snapshotRestore.restoreForm.dataStreamsWarningCallOut.body.learnMoreLink', + { defaultMessage: 'Learn more' } + )} + + ), + }} + /> + ), + }, +}; + +interface Props { + dataStreamsCount: number; +} + +export const DataStreamsGlobalStateCallOut: FunctionComponent = ({ dataStreamsCount }) => { + return ( + + {i18nTexts.callout.body()} + + ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index 0b740734dcc46..3171ba3030fb5 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -33,6 +33,8 @@ import { orderDataStreamsAndIndices, DataStreamBadge } from '../../../shared'; import { StepProps } from '../index'; +import { DataStreamsGlobalStateCallOut } from './data_streams_global_state_call_out'; + export const RestoreSnapshotStepLogistics: React.FunctionComponent = ({ snapshotDetails, restoreSettings, @@ -42,7 +44,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = const { i18n } = useServices(); const { indices: unfilteredSnapshotIndices, - dataStreams: snapshotDataStreams, + dataStreams: snapshotDataStreams = [], includeGlobalState: snapshotIncludeGlobalState, } = snapshotDetails; @@ -167,6 +169,11 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = + + {snapshotDataStreams.length ? ( + + ) : undefined} + {/* Indices */} diff --git a/x-pack/plugins/snapshot_restore/public/application/components/shared/helpers.ts b/x-pack/plugins/snapshot_restore/public/application/components/shared/helpers.ts new file mode 100644 index 0000000000000..f21576778a0ea --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/shared/helpers.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +export const orderDataStreamsAndIndices = ({ + dataStreams, + indices, +}: { + dataStreams: D[]; + indices: D[]; +}) => { + return dataStreams.concat(indices); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/shared/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/shared/index.ts new file mode 100644 index 0000000000000..8d1695ec403ed --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/shared/index.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +export { DataStreamBadge } from './data_stream_badge'; + +export { orderDataStreamsAndIndices } from './helpers'; diff --git a/x-pack/plugins/snapshot_restore/public/application/services/documentation/documentation_links.ts b/x-pack/plugins/snapshot_restore/public/application/services/documentation/documentation_links.ts index daeb14c39f68b..59fdedb772378 100644 --- a/x-pack/plugins/snapshot_restore/public/application/services/documentation/documentation_links.ts +++ b/x-pack/plugins/snapshot_restore/public/application/services/documentation/documentation_links.ts @@ -72,6 +72,10 @@ class DocumentationLinksService { public getCronUrl() { return `${this.esDocBasePath}trigger-schedule.html#schedule-cron`; } + + public getCreateIndexTemplateForDataStream() { + return `${this.esDocBasePath}set-up-a-data-stream.html#create-a-data-stream-template`; + } } export const documentationLinksService = new DocumentationLinksService(); From 7c742ef3a46ef073ee0a66732b290e89ba849422 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 30 Jun 2020 16:30:36 +0200 Subject: [PATCH 29/43] restore CITs --- .../client_integration/helpers/index.ts | 2 + .../helpers/restore_snapshot.helpers.ts | 51 +++++++++++++++++++ ...policy_add.test.tsx => policy_add.test.ts} | 0 .../restore_snapshot.test.ts | 49 ++++++++++++++++++ .../data_streams_global_state_call_out.tsx | 7 ++- .../steps/step_logistics/step_logistics.tsx | 5 +- .../test/fixtures/snapshot.ts | 13 ++++- 7 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/restore_snapshot.helpers.ts rename x-pack/plugins/snapshot_restore/__jest__/client_integration/{policy_add.test.tsx => policy_add.test.ts} (100%) create mode 100644 x-pack/plugins/snapshot_restore/__jest__/client_integration/restore_snapshot.test.ts diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/index.ts index e8efe94396b2a..69d1423f5f8fb 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/index.ts @@ -9,6 +9,7 @@ import { setup as repositoryAddSetup } from './repository_add.helpers'; import { setup as repositoryEditSetup } from './repository_edit.helpers'; import { setup as policyAddSetup } from './policy_add.helpers'; import { setup as policyEditSetup } from './policy_edit.helpers'; +import { setup as restoreSnapshotSetup } from './restore_snapshot.helpers'; export { nextTick, getRandomString, findTestSubject, TestBed } from '../../../../../test_utils'; @@ -20,4 +21,5 @@ export const pageHelpers = { repositoryEdit: { setup: repositoryEditSetup }, policyAdd: { setup: policyAddSetup }, policyEdit: { setup: policyEditSetup }, + restoreSnapshot: { setup: restoreSnapshotSetup }, }; diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/restore_snapshot.helpers.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/restore_snapshot.helpers.ts new file mode 100644 index 0000000000000..db366f917e4a8 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/restore_snapshot.helpers.ts @@ -0,0 +1,51 @@ +/* + * 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. + */ +/* eslint-disable @kbn/eslint/no-restricted-paths */ + +import { registerTestBed, TestBed, TestBedConfig } from '../../../../../test_utils'; +import { RestoreSnapshot } from '../../../public/application/sections/restore_snapshot'; +import { WithAppDependencies } from './setup_environment'; + +const testBedConfig: TestBedConfig = { + memoryRouter: { + initialEntries: ['/add_policy'], + componentRoutePath: '/add_policy', + }, + doMountAsync: true, +}; + +const initTestBed = registerTestBed( + WithAppDependencies(RestoreSnapshot), + testBedConfig +); + +const setupActions = (testBed: TestBed) => { + const { find } = testBed; + return { + findDataStreamCallout() { + return find('dataStreamWarningCallOut'); + }, + }; +}; + +type Actions = ReturnType; + +export type RestoreSnapshotTestBed = TestBed & { + actions: Actions; +}; + +export const setup = async (): Promise => { + const testBed = await initTestBed(); + + return { + ...testBed, + actions: setupActions(testBed), + }; +}; + +export type RestoreSnapshotFormTestSubject = + | 'snapshotRestoreStepLogistics' + | 'dataStreamWarningCallOut'; diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.tsx b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts similarity index 100% rename from x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.tsx rename to x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/restore_snapshot.test.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/restore_snapshot.test.ts new file mode 100644 index 0000000000000..17d714c07429f --- /dev/null +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/restore_snapshot.test.ts @@ -0,0 +1,49 @@ +/* + * 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 { nextTick, pageHelpers, setupEnvironment } from './helpers'; +import { RestoreSnapshotTestBed } from './helpers/restore_snapshot.helpers'; +import * as fixtures from '../../test/fixtures'; + +const { + restoreSnapshot: { setup }, +} = pageHelpers; + +describe('', () => { + const { server, httpRequestsMockHelpers } = setupEnvironment(); + let testBed: RestoreSnapshotTestBed; + + afterAll(() => { + server.restore(); + }); + describe('with data streams', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setGetSnapshotResponse(fixtures.getSnapshot()); + testBed = await setup(); + await nextTick(); + testBed.component.update(); + }); + + it('shows the data streams warning when the snapshot has data streams', () => { + const { exists } = testBed; + expect(exists('dataStreamWarningCallOut')).toBe(true); + }); + }); + + describe('without data streams', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setGetSnapshotResponse(fixtures.getSnapshot({ totalDataStreams: 0 })); + testBed = await setup(); + await nextTick(); + testBed.component.update(); + }); + + it('hides the data streams warning when the snapshot has data streams', () => { + const { exists } = testBed; + expect(exists('dataStreamWarningCallOut')).toBe(false); + }); + }); +}); diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx index 239d1413b27b7..5758d3daf7490 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx @@ -46,7 +46,12 @@ interface Props { export const DataStreamsGlobalStateCallOut: FunctionComponent = ({ dataStreamsCount }) => { return ( - + {i18nTexts.callout.body()} ); diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index 3171ba3030fb5..d01a8a34ff0f9 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -140,7 +140,10 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = }); return ( -
+
{/* Step title and doc link */} diff --git a/x-pack/plugins/snapshot_restore/test/fixtures/snapshot.ts b/x-pack/plugins/snapshot_restore/test/fixtures/snapshot.ts index be0550d9c6b54..e59f4689d9e3f 100644 --- a/x-pack/plugins/snapshot_restore/test/fixtures/snapshot.ts +++ b/x-pack/plugins/snapshot_restore/test/fixtures/snapshot.ts @@ -13,14 +13,23 @@ export const getSnapshot = ({ state = 'SUCCESS', indexFailures = [], totalIndices = getRandomNumber(), -} = {}) => ({ + totalDataStreams = getRandomNumber(), +}: Partial<{ + repository: string; + snapshot: string; + uuid: string; + state: string; + indexFailures: any[]; + totalIndices: number; + totalDataStreams: number; +}> = {}) => ({ repository, snapshot, uuid, versionId: 8000099, version: '8.0.0', indices: new Array(totalIndices).fill('').map(getRandomString), - dataStreams: [], + dataStreams: new Array(totalDataStreams).fill('').map(getRandomString), includeGlobalState: 1, state, startTime: '2019-05-23T06:25:15.896Z', From 0f19ee5901b126354a749e3a8499882588bd326e Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 1 Jul 2020 12:38:09 +0200 Subject: [PATCH 30/43] first round of copy feedback --- .../policy_form/steps/step_review.tsx | 8 ++-- .../indices_and_data_streams_field.tsx | 14 +++---- .../steps/step_settings/step_settings.tsx | 2 +- .../data_streams_global_state_call_out.tsx | 9 ++--- .../steps/step_logistics/step_logistics.tsx | 38 +++++++++---------- .../steps/step_review.tsx | 4 +- .../policy_details/tabs/tab_summary.tsx | 4 +- .../documentation/documentation_links.ts | 4 -- .../translations/translations/ja-JP.json | 16 -------- .../translations/translations/zh-CN.json | 16 -------- 10 files changed, 38 insertions(+), 77 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx index a95e0515fef0f..6b253a3fada05 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_review.tsx @@ -148,8 +148,8 @@ export const PolicyStepReview: React.FunctionComponent = ({ @@ -187,8 +187,8 @@ export const PolicyStepReview: React.FunctionComponent = ({ diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx index 3eb7e11e1f407..ac575eb061300 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx @@ -97,8 +97,8 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({ } checked={isAllIndices} @@ -136,16 +136,16 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({

} description={ } fullWidth @@ -180,7 +180,7 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({ diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx index 4f21f2855b4a7..9d43c45d17ea7 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/step_settings.tsx @@ -133,7 +133,7 @@ export const PolicyStepSettings: React.FunctionComponent = ({ description={ } fullWidth diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx index 5758d3daf7490..ebef440ea1bdd 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx @@ -15,19 +15,16 @@ const i18nTexts = { callout: { title: (count: number) => i18n.translate('xpack.snapshotRestore.restoreForm.dataStreamsWarningCallOut.title', { - defaultMessage: 'Data {count, plural, one {stream} other {streams}} found in this snapshot', + defaultMessage: 'This snapshot contains data {count, plural, one {stream} other {streams}}', values: { count }, }), body: () => ( + {i18n.translate( 'xpack.snapshotRestore.restoreForm.dataStreamsWarningCallOut.body.learnMoreLink', { defaultMessage: 'Learn more' } diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index d01a8a34ff0f9..980bf725b216c 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -185,16 +185,16 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent =

} description={ } @@ -205,8 +205,8 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = } checked={isAllIndicesAndDataStreams} @@ -235,8 +235,8 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = @@ -269,8 +269,8 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = }} >
@@ -280,8 +280,8 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = helpText={ selectIndicesMode === 'list' ? ( =

} description={ } fullWidth @@ -443,8 +443,8 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = } checked={isRenamingIndices} @@ -583,7 +583,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = } fullWidth diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_review.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_review.tsx index 1ce0669485f1e..5dacba506fe18 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_review.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_review.tsx @@ -73,8 +73,8 @@ export const RestoreSnapshotStepReview: React.FunctionComponent = ({ diff --git a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/tabs/tab_summary.tsx b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/tabs/tab_summary.tsx index 7bcee4f5f6621..e69b0fad8014e 100644 --- a/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/tabs/tab_summary.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/sections/home/policy_list/policy_details/tabs/tab_summary.tsx @@ -236,8 +236,8 @@ export const TabSummary: React.FunctionComponent = ({ policy }) => { diff --git a/x-pack/plugins/snapshot_restore/public/application/services/documentation/documentation_links.ts b/x-pack/plugins/snapshot_restore/public/application/services/documentation/documentation_links.ts index 59fdedb772378..daeb14c39f68b 100644 --- a/x-pack/plugins/snapshot_restore/public/application/services/documentation/documentation_links.ts +++ b/x-pack/plugins/snapshot_restore/public/application/services/documentation/documentation_links.ts @@ -72,10 +72,6 @@ class DocumentationLinksService { public getCronUrl() { return `${this.esDocBasePath}trigger-schedule.html#schedule-cron`; } - - public getCreateIndexTemplateForDataStream() { - return `${this.esDocBasePath}set-up-a-data-stream.html#create-a-data-stream-template`; - } } export const documentationLinksService = new DocumentationLinksService(); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 0b466f351d7db..65c99bd71562b 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -14907,7 +14907,6 @@ "xpack.snapshotRestore.policyDetails.includeGlobalStateFalseLabel": "いいえ", "xpack.snapshotRestore.policyDetails.includeGlobalStateLabel": "グローバルステータスを含める", "xpack.snapshotRestore.policyDetails.includeGlobalStateTrueLabel": "はい", - "xpack.snapshotRestore.policyDetails.indicesLabel": "インデックス", "xpack.snapshotRestore.policyDetails.inProgressSnapshotLinkText": "「{snapshotName}」が進行中", "xpack.snapshotRestore.policyDetails.lastFailure.dateLabel": "日付", "xpack.snapshotRestore.policyDetails.lastFailure.detailsAriaLabel": "ポリシー「{name}」の前回のエラーの詳細", @@ -15015,10 +15014,8 @@ "xpack.snapshotRestore.policyForm.stepReview.summaryTab.includeGlobalStateFalseLabel": "いいえ", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.includeGlobalStateLabel": "グローバルステータスを含める", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.includeGlobalStateTrueLabel": "はい", - "xpack.snapshotRestore.policyForm.stepReview.summaryTab.indicesLabel": "インデックス", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.nameLabel": "ポリシー名", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.partialFalseLabel": "いいえ", - "xpack.snapshotRestore.policyForm.stepReview.summaryTab.partialLabel": "部分シャードを許可", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.partialTrueLabel": "はい", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.repositoryLabel": "レポジトリ", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.scheduleLabel": "スケジュール", @@ -15027,7 +15024,6 @@ "xpack.snapshotRestore.policyForm.stepReview.summaryTab.snapshotNameLabel": "スナップショット名", "xpack.snapshotRestore.policyForm.stepReview.summaryTabTitle": "まとめ", "xpack.snapshotRestore.policyForm.stepReviewTitle": "レビューポリシー", - "xpack.snapshotRestore.policyForm.stepSettings.allIndicesLabel": "システムインデックスを含むすべてのインデックス", "xpack.snapshotRestore.policyForm.stepSettings.deselectAllIndicesLink": "すべて選択解除", "xpack.snapshotRestore.policyForm.stepSettings.docsButtonLabel": "スナップショット設定ドキュメント", "xpack.snapshotRestore.policyForm.stepSettings.ignoreUnavailableDescription": "スナップショットの撮影時に利用不可能なインデックスを無視します。これが設定されていない場合、スナップショット全体がエラーになります。", @@ -15035,10 +15031,8 @@ "xpack.snapshotRestore.policyForm.stepSettings.ignoreUnavailableLabel": "利用不可能なインデックスを無視", "xpack.snapshotRestore.policyForm.stepSettings.includeGlobalStateDescription": "スナップショットの一部としてクラスターのグローバルステータスを格納します。", "xpack.snapshotRestore.policyForm.stepSettings.includeGlobalStateDescriptionTitle": "グローバルステータスを含める", - "xpack.snapshotRestore.policyForm.stepSettings.indicesDescription": "バックアップするインデックスです。", "xpack.snapshotRestore.policyForm.stepSettings.indicesPatternLabel": "インデックスパターン", "xpack.snapshotRestore.policyForm.stepSettings.indicesPatternPlaceholder": "logstash-* などのインデックスパターンを入力", - "xpack.snapshotRestore.policyForm.stepSettings.indicesTitle": "インデックス", "xpack.snapshotRestore.policyForm.stepSettings.indicesToggleCustomLink": "インデックスパターンを使用", "xpack.snapshotRestore.policyForm.stepSettings.indicesToggleListLink": "インデックスを選択", "xpack.snapshotRestore.policyForm.stepSettings.indicesTooltip": "クラウドで管理されたポリシーにはすべてのインデックスが必要です。", @@ -15394,31 +15388,22 @@ "xpack.snapshotRestore.restoreForm.navigation.stepSettingsName": "インデックス設定", "xpack.snapshotRestore.restoreForm.nextButtonLabel": "次へ", "xpack.snapshotRestore.restoreForm.savingButtonLabel": "復元中...", - "xpack.snapshotRestore.restoreForm.stepLogistics.allIndicesLabel": "システムインデックスを含むすべてのインデックス", "xpack.snapshotRestore.restoreForm.stepLogistics.deselectAllIndicesLink": "すべて選択解除", "xpack.snapshotRestore.restoreForm.stepLogistics.docsButtonLabel": "スナップショットと復元ドキュメント", "xpack.snapshotRestore.restoreForm.stepLogistics.includeGlobalStateDescription": "現在クラスターに存在しないテンプレートを復元し、テンプレートを同じ名前で上書きします。永続的な設定も復元します。", "xpack.snapshotRestore.restoreForm.stepLogistics.includeGlobalStateDisabledDescription": "このスナップショットでは使用できません。", "xpack.snapshotRestore.restoreForm.stepLogistics.includeGlobalStateLabel": "グローバル状態の復元", "xpack.snapshotRestore.restoreForm.stepLogistics.includeGlobalStateTitle": "グローバル状態の復元", - "xpack.snapshotRestore.restoreForm.stepLogistics.indicesDescription": "存在しない場合は、新しいインデックスを作成します。閉じていて、スナップショットインデックスと同じ数のシャードがある場合は、既存のインデックスを復元します。", "xpack.snapshotRestore.restoreForm.stepLogistics.indicesPatternLabel": "インデックスパターン", "xpack.snapshotRestore.restoreForm.stepLogistics.indicesPatternPlaceholder": "logstash-* などのインデックスパターンを入力", - "xpack.snapshotRestore.restoreForm.stepLogistics.indicesTitle": "インデックス", "xpack.snapshotRestore.restoreForm.stepLogistics.indicesToggleCustomLink": "インデックスパターンを使用", - "xpack.snapshotRestore.restoreForm.stepLogistics.indicesToggleListLink": "インデックスを選択", "xpack.snapshotRestore.restoreForm.stepLogistics.partialDescription": "すべてのシャードのスナップショットがないインデックスを復元できます。", "xpack.snapshotRestore.restoreForm.stepLogistics.partialLabel": "部分復元", "xpack.snapshotRestore.restoreForm.stepLogistics.partialTitle": "部分復元", - "xpack.snapshotRestore.restoreForm.stepLogistics.renameIndicesDescription": "復元時にインデックス名を変更します。", - "xpack.snapshotRestore.restoreForm.stepLogistics.renameIndicesLabel": "インデックス名の変更", - "xpack.snapshotRestore.restoreForm.stepLogistics.renameIndicesTitle": "インデックス名の変更", "xpack.snapshotRestore.restoreForm.stepLogistics.renamePatternHelpText": "正規表現を使用", "xpack.snapshotRestore.restoreForm.stepLogistics.renamePatternLabel": "取り込みパターン", "xpack.snapshotRestore.restoreForm.stepLogistics.renameReplacementLabel": "置換パターン", "xpack.snapshotRestore.restoreForm.stepLogistics.selectAllIndicesLink": "すべて選択", - "xpack.snapshotRestore.restoreForm.stepLogistics.selectIndicesHelpText": "{count} 件の{count, plural, one {インデックス} other {インデックス}}が復元されます。{selectOrDeselectAllLink}", - "xpack.snapshotRestore.restoreForm.stepLogistics.selectIndicesLabel": "インデックスを選択", "xpack.snapshotRestore.restoreForm.stepLogisticsTitle": "詳細を復元", "xpack.snapshotRestore.restoreForm.stepReview.jsonTab.jsonAriaLabel": "実行する設定を復元", "xpack.snapshotRestore.restoreForm.stepReview.jsonTabTitle": "JSON", @@ -15428,7 +15413,6 @@ "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.includeGlobalStateLabel": "グローバル状態の復元", "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.includeGlobalStateTrueValue": "はい", "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.indexSettingsLabel": "修正", - "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.indicesLabel": "インデックス", "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.noSettingsValue": "インデックス設定の修正はありません", "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.partialFalseValue": "いいえ", "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.partialLabel": "部分復元", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 52c01d292cacc..bb4d4f6c36843 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -14913,7 +14913,6 @@ "xpack.snapshotRestore.policyDetails.includeGlobalStateFalseLabel": "否", "xpack.snapshotRestore.policyDetails.includeGlobalStateLabel": "包括全局状态", "xpack.snapshotRestore.policyDetails.includeGlobalStateTrueLabel": "是", - "xpack.snapshotRestore.policyDetails.indicesLabel": "索引", "xpack.snapshotRestore.policyDetails.inProgressSnapshotLinkText": "“{snapshotName}”正在进行中", "xpack.snapshotRestore.policyDetails.lastFailure.dateLabel": "日期", "xpack.snapshotRestore.policyDetails.lastFailure.detailsAriaLabel": "策略“{name}”的上次失败详情", @@ -15021,10 +15020,8 @@ "xpack.snapshotRestore.policyForm.stepReview.summaryTab.includeGlobalStateFalseLabel": "否", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.includeGlobalStateLabel": "包括全局状态", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.includeGlobalStateTrueLabel": "是", - "xpack.snapshotRestore.policyForm.stepReview.summaryTab.indicesLabel": "索引", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.nameLabel": "策略名称", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.partialFalseLabel": "否", - "xpack.snapshotRestore.policyForm.stepReview.summaryTab.partialLabel": "允许部分分片", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.partialTrueLabel": "是", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.repositoryLabel": "存储库", "xpack.snapshotRestore.policyForm.stepReview.summaryTab.scheduleLabel": "计划", @@ -15033,7 +15030,6 @@ "xpack.snapshotRestore.policyForm.stepReview.summaryTab.snapshotNameLabel": "快照名称", "xpack.snapshotRestore.policyForm.stepReview.summaryTabTitle": "总结", "xpack.snapshotRestore.policyForm.stepReviewTitle": "复查策略", - "xpack.snapshotRestore.policyForm.stepSettings.allIndicesLabel": "所有索引,包括系统索引", "xpack.snapshotRestore.policyForm.stepSettings.deselectAllIndicesLink": "取消全选", "xpack.snapshotRestore.policyForm.stepSettings.docsButtonLabel": "快照设置文档", "xpack.snapshotRestore.policyForm.stepSettings.ignoreUnavailableDescription": "拍取快照时忽略不可用的索引。否则,整个快照将失败。", @@ -15041,10 +15037,8 @@ "xpack.snapshotRestore.policyForm.stepSettings.ignoreUnavailableLabel": "忽略不可用索引", "xpack.snapshotRestore.policyForm.stepSettings.includeGlobalStateDescription": "将集群的全局状态存储为快照的一部分。", "xpack.snapshotRestore.policyForm.stepSettings.includeGlobalStateDescriptionTitle": "包括全局状态", - "xpack.snapshotRestore.policyForm.stepSettings.indicesDescription": "要备份的索引。", "xpack.snapshotRestore.policyForm.stepSettings.indicesPatternLabel": "索引模式", "xpack.snapshotRestore.policyForm.stepSettings.indicesPatternPlaceholder": "输入索引模式,例如 logstash-*", - "xpack.snapshotRestore.policyForm.stepSettings.indicesTitle": "索引", "xpack.snapshotRestore.policyForm.stepSettings.indicesToggleCustomLink": "使用索引模式", "xpack.snapshotRestore.policyForm.stepSettings.indicesToggleListLink": "选择索引", "xpack.snapshotRestore.policyForm.stepSettings.indicesTooltip": "云托管的策略需要所有索引。", @@ -15400,31 +15394,22 @@ "xpack.snapshotRestore.restoreForm.navigation.stepSettingsName": "索引设置", "xpack.snapshotRestore.restoreForm.nextButtonLabel": "下一步", "xpack.snapshotRestore.restoreForm.savingButtonLabel": "正在还原……", - "xpack.snapshotRestore.restoreForm.stepLogistics.allIndicesLabel": "所有索引,包括系统索引", "xpack.snapshotRestore.restoreForm.stepLogistics.deselectAllIndicesLink": "取消全选", "xpack.snapshotRestore.restoreForm.stepLogistics.docsButtonLabel": "快照和还原文档", "xpack.snapshotRestore.restoreForm.stepLogistics.includeGlobalStateDescription": "还原当前在集群中不存在的模板并覆盖同名模板。同时还原永久性设置。", "xpack.snapshotRestore.restoreForm.stepLogistics.includeGlobalStateDisabledDescription": "不适用于此快照。", "xpack.snapshotRestore.restoreForm.stepLogistics.includeGlobalStateLabel": "还原全局状态", "xpack.snapshotRestore.restoreForm.stepLogistics.includeGlobalStateTitle": "还原全局状态", - "xpack.snapshotRestore.restoreForm.stepLogistics.indicesDescription": "如果不存在,则创建新索引。如果现有索引已关闭且与快照索引有相同数目的分片,则还原现有索引。", "xpack.snapshotRestore.restoreForm.stepLogistics.indicesPatternLabel": "索引模式", "xpack.snapshotRestore.restoreForm.stepLogistics.indicesPatternPlaceholder": "输入索引模式,例如 logstash-*", - "xpack.snapshotRestore.restoreForm.stepLogistics.indicesTitle": "索引", "xpack.snapshotRestore.restoreForm.stepLogistics.indicesToggleCustomLink": "使用索引模式", - "xpack.snapshotRestore.restoreForm.stepLogistics.indicesToggleListLink": "选择索引", "xpack.snapshotRestore.restoreForm.stepLogistics.partialDescription": "允许还原不具有所有分片的快照的索引。", "xpack.snapshotRestore.restoreForm.stepLogistics.partialLabel": "部分还原", "xpack.snapshotRestore.restoreForm.stepLogistics.partialTitle": "部分还原", - "xpack.snapshotRestore.restoreForm.stepLogistics.renameIndicesDescription": "还原时重命名索引。", - "xpack.snapshotRestore.restoreForm.stepLogistics.renameIndicesLabel": "重命名索引", - "xpack.snapshotRestore.restoreForm.stepLogistics.renameIndicesTitle": "重命名索引", "xpack.snapshotRestore.restoreForm.stepLogistics.renamePatternHelpText": "使用正则表达式", "xpack.snapshotRestore.restoreForm.stepLogistics.renamePatternLabel": "捕获模式", "xpack.snapshotRestore.restoreForm.stepLogistics.renameReplacementLabel": "替换模式", "xpack.snapshotRestore.restoreForm.stepLogistics.selectAllIndicesLink": "全选", - "xpack.snapshotRestore.restoreForm.stepLogistics.selectIndicesHelpText": "将还原 {count} 个 {count, plural, one {索引} other {索引}}。{selectOrDeselectAllLink}", - "xpack.snapshotRestore.restoreForm.stepLogistics.selectIndicesLabel": "选择索引", "xpack.snapshotRestore.restoreForm.stepLogisticsTitle": "还原详情", "xpack.snapshotRestore.restoreForm.stepReview.jsonTab.jsonAriaLabel": "还原要执行的设置", "xpack.snapshotRestore.restoreForm.stepReview.jsonTabTitle": "JSON", @@ -15434,7 +15419,6 @@ "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.includeGlobalStateLabel": "还原全局状态", "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.includeGlobalStateTrueValue": "鏄", "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.indexSettingsLabel": "修改", - "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.indicesLabel": "索引", "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.noSettingsValue": "无索引设置修改", "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.partialFalseValue": "否", "xpack.snapshotRestore.restoreForm.stepReview.summaryTab.partialLabel": "部分还原", From 08d0ab96b17643506f97d0cd43f096703720824c Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 1 Jul 2020 13:37:37 +0200 Subject: [PATCH 31/43] refactor help text to provide clearer feedback, for both restore and policy forms --- .../client_integration/policy_add.test.ts | 4 +- ...ata_streams_and_indices_list_help_text.tsx | 78 +++++++++++++++ .../indices_and_data_streams_field.tsx | 99 ++++++++----------- ...ata_streams_and_indices_list_help_text.tsx | 78 +++++++++++++++ .../steps/step_logistics/step_logistics.tsx | 83 ++++++---------- .../services/validation/validate_policy.ts | 2 +- .../services/validation/validate_restore.ts | 4 +- .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 9 files changed, 234 insertions(+), 118 deletions(-) create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/data_streams_and_indices_list_help_text.tsx create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_and_indices_list_help_text.tsx diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts index 3164af519ae10..17a745fafcc26 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/policy_add.test.ts @@ -115,7 +115,9 @@ describe('', () => { // Deselect all indices from list find('deselectIndicesLink').simulate('click'); - expect(form.getErrorsMessages()).toEqual(['You must select at least one index.']); + expect(form.getErrorsMessages()).toEqual([ + 'You must select at least one data stream or index.', + ]); }); test('should correctly indicate data streams with a badge', async () => { diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/data_streams_and_indices_list_help_text.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/data_streams_and_indices_list_help_text.tsx new file mode 100644 index 0000000000000..93b481f97605c --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/data_streams_and_indices_list_help_text.tsx @@ -0,0 +1,78 @@ +/* + * 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 React, { FunctionComponent } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiLink } from '@elastic/eui'; + +interface Props { + onSelectionChange: (selection: 'all' | 'none') => void; + selectedIndicesAndDataStreams: string[]; + indices: string[]; + dataStreams: string[]; +} + +export const DataStreamsAndIndicesListHelpText: FunctionComponent = ({ + onSelectionChange, + selectedIndicesAndDataStreams, + indices, + dataStreams, +}) => { + const indicesCount = selectedIndicesAndDataStreams.reduce( + (acc, v) => (indices.includes(v) ? acc + 1 : acc), + 0 + ); + const dataStreamsCount = selectedIndicesAndDataStreams.reduce( + (acc, v) => (dataStreams.includes(v) ? acc + 1 : acc), + 0 + ); + const i18nValues = { + indicesCount, + dataStreamsCount, + selectOrDeselectAllLink: + selectedIndicesAndDataStreams.length > 0 ? ( + { + onSelectionChange('none'); + }} + > + + + ) : ( + { + onSelectionChange('all'); + }} + > + + + ), + }; + + if (selectedIndicesAndDataStreams.length === 0) { + return ( + + ); + } + return ( + + ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx index ac575eb061300..435e78ca89b86 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx @@ -31,6 +31,8 @@ import { orderDataStreamsAndIndices, DataStreamBadge } from '../../../../../shar import { mapSelectionToIndicesOptions, determineListMode } from './helpers'; +import { DataStreamsAndIndicesListHelpText } from './data_streams_and_indices_list_help_text'; + interface Props { isManagedPolicy: boolean; policy: SlmPolicyPayload; @@ -63,16 +65,19 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({ !config.indices || (Array.isArray(config.indices) && config.indices.length === 0) ); - const [indicesSelection, setIndicesSelection] = useState(() => - Array.isArray(config.indices) && !isAllIndices - ? indicesAndDataStreams.filter((i) => (config.indices! as string[]).includes(i)) - : [...indicesAndDataStreams] + const [indicesAndDataStreamsSelection, setIndicesAndDataStreamsSelection] = useState( + () => + Array.isArray(config.indices) && !isAllIndices + ? indicesAndDataStreams.filter((i) => (config.indices! as string[]).includes(i)) + : [...indicesAndDataStreams] ); // States for choosing all indices, or a subset, including caching previously chosen subset list - const [indicesOptions, setIndicesOptions] = useState(() => + const [indicesAndDataStreamsOptions, setIndicesAndDataStreamsOptions] = useState< + EuiSelectableOption[] + >(() => mapSelectionToIndicesOptions({ - selection: indicesSelection, + selection: indicesAndDataStreamsSelection, dataStreams, indices, allSelected: isAllIndices || typeof config.indices === 'string', @@ -108,13 +113,13 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({ const isChecked = e.target.checked; setIsAllIndices(isChecked); if (isChecked) { - setIndicesSelection(indicesAndDataStreams); - setIndicesOptions( + setIndicesAndDataStreamsSelection(indicesAndDataStreams); + setIndicesAndDataStreamsOptions( mapSelectionToIndicesOptions({ allSelected: isAllIndices || typeof config.indices === 'string', dataStreams, indices, - selection: indicesSelection, + selection: indicesAndDataStreamsSelection, }) ); onUpdate({ indices: undefined }); @@ -123,7 +128,7 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({ indices: selectIndicesMode === 'custom' ? indexPatterns.join(',') - : [...(indicesSelection || [])], + : [...(indicesAndDataStreamsSelection || [])], }); } }} @@ -145,7 +150,7 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({ description={ } fullWidth @@ -210,12 +215,12 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({ data-test-subj="selectIndicesLink" onClick={() => { setSelectIndicesMode('list'); - onUpdate({ indices: indicesSelection }); + onUpdate({ indices: indicesAndDataStreamsSelection }); }} > @@ -224,47 +229,27 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({ } helpText={ selectIndicesMode === 'list' ? ( - 0 ? ( - { - // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed - indicesOptions.forEach((option: EuiSelectableOption) => { - option.checked = undefined; - }); - onUpdate({ indices: [] }); - setIndicesSelection([]); - }} - > - - - ) : ( - { - // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed - indicesOptions.forEach((option: EuiSelectableOption) => { - option.checked = 'on'; - }); - onUpdate({ indices: [...indices] }); - setIndicesSelection([...indices]); - }} - > - - - ), + { + if (selection === 'all') { + // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed + indicesAndDataStreamsOptions.forEach((option: EuiSelectableOption) => { + option.checked = 'on'; + }); + onUpdate({ indices: [...indicesAndDataStreams] }); + setIndicesAndDataStreamsSelection([...indicesAndDataStreams]); + } else { + // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed + indicesAndDataStreamsOptions.forEach((option: EuiSelectableOption) => { + option.checked = undefined; + }); + onUpdate({ indices: [] }); + setIndicesAndDataStreamsSelection([]); + } }} + selectedIndicesAndDataStreams={indicesAndDataStreamsSelection} + indices={indices} + dataStreams={dataStreams} /> ) : null } @@ -275,7 +260,7 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({ { const newSelectedIndices: string[] = []; options.forEach(({ label, checked }) => { @@ -283,9 +268,9 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({ newSelectedIndices.push(label); } }); - setIndicesOptions(options); + setIndicesAndDataStreamsOptions(options); onUpdate({ indices: newSelectedIndices }); - setIndicesSelection(newSelectedIndices); + setIndicesAndDataStreamsSelection(newSelectedIndices); }} searchable height={300} diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_and_indices_list_help_text.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_and_indices_list_help_text.tsx new file mode 100644 index 0000000000000..6f432d2468ab4 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_and_indices_list_help_text.tsx @@ -0,0 +1,78 @@ +/* + * 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 React, { FunctionComponent } from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiLink } from '@elastic/eui'; + +interface Props { + onSelectionChange: (selection: 'all' | 'none') => void; + selectedIndicesAndDataStreams: string[]; + indices: string[]; + dataStreams: string[]; +} + +export const DataStreamsAndIndicesListHelpText: FunctionComponent = ({ + onSelectionChange, + selectedIndicesAndDataStreams, + indices, + dataStreams, +}) => { + const indicesCount = selectedIndicesAndDataStreams.reduce( + (acc, v) => (indices.includes(v) ? acc + 1 : acc), + 0 + ); + const dataStreamsCount = selectedIndicesAndDataStreams.reduce( + (acc, v) => (dataStreams.includes(v) ? acc + 1 : acc), + 0 + ); + const i18nValues = { + indicesCount, + dataStreamsCount, + selectOrDeselectAllLink: + selectedIndicesAndDataStreams.length > 0 ? ( + { + onSelectionChange('none'); + }} + > + + + ) : ( + { + onSelectionChange('all'); + }} + > + + + ), + }; + + if (selectedIndicesAndDataStreams.length === 0) { + return ( + + ); + } + return ( + + ); +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index 980bf725b216c..ce0ef6ddea69f 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -22,7 +22,7 @@ import { } from '@elastic/eui'; import { EuiSelectableOption } from '@elastic/eui'; -import { isDataStreamBackingIndex } from '../../../../../../common/lib'; +import { indicesToArray, isDataStreamBackingIndex } from '../../../../../../common/lib'; import { RestoreSettings } from '../../../../../../common/types'; import { documentationLinksService } from '../../../../services/documentation'; @@ -35,6 +35,8 @@ import { StepProps } from '../index'; import { DataStreamsGlobalStateCallOut } from './data_streams_global_state_call_out'; +import { DataStreamsAndIndicesListHelpText } from './data_streams_and_indices_list_help_text'; + export const RestoreSnapshotStepLogistics: React.FunctionComponent = ({ snapshotDetails, restoreSettings, @@ -279,58 +281,35 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = } helpText={ selectIndicesMode === 'list' ? ( - 0 ? ( - { - // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed - indicesAndDataStreamsOptions.forEach( - (option: EuiSelectableOption) => { - option.checked = undefined; - } - ); - updateRestoreSettings({ indices: [] }); - setCachedRestoreSettings({ - ...cachedRestoreSettings, - indices: [], - }); - }} - > - - - ) : ( - { - // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed - indicesAndDataStreamsOptions.forEach( - (option: EuiSelectableOption) => { - option.checked = 'on'; - } - ); - updateRestoreSettings({ - indices: [...snapshotIndicesAndDataStreams], - }); - setCachedRestoreSettings({ - ...cachedRestoreSettings, - indices: [...snapshotIndicesAndDataStreams], - }); - }} - > - - - ), + { + if (selection === 'all') { + // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed + indicesAndDataStreamsOptions.forEach((option: EuiSelectableOption) => { + option.checked = 'on'; + }); + updateRestoreSettings({ + indices: [...snapshotIndicesAndDataStreams], + }); + setCachedRestoreSettings({ + ...cachedRestoreSettings, + indices: [...snapshotIndicesAndDataStreams], + }); + } else { + // TODO: Change this to setIndicesOptions() when https://github.com/elastic/eui/issues/2071 is fixed + indicesAndDataStreamsOptions.forEach((option: EuiSelectableOption) => { + option.checked = undefined; + }); + updateRestoreSettings({ indices: [] }); + setCachedRestoreSettings({ + ...cachedRestoreSettings, + indices: [], + }); + } }} + selectedIndicesAndDataStreams={indicesToArray(restoreIndices)} + indices={snapshotIndices} + dataStreams={snapshotDataStreams} /> ) : null } diff --git a/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_policy.ts b/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_policy.ts index 75aba5953231c..24960b2533230 100644 --- a/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_policy.ts +++ b/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_policy.ts @@ -107,7 +107,7 @@ export const validatePolicy = ( if (config && Array.isArray(config.indices) && config.indices.length === 0) { validation.errors.indices.push( i18n.translate('xpack.snapshotRestore.policyValidation.indicesRequiredErrorMessage', { - defaultMessage: 'You must select at least one index.', + defaultMessage: 'You must select at least one data stream or index.', }) ); } diff --git a/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_restore.ts b/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_restore.ts index 5c1a1fbfab12d..93e278e51f093 100644 --- a/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_restore.ts +++ b/x-pack/plugins/snapshot_restore/public/application/services/validation/validate_restore.ts @@ -48,7 +48,7 @@ export const validateRestore = (restoreSettings: RestoreSettings): RestoreValida if (Array.isArray(indices) && indices.length === 0) { validation.errors.indices.push( i18n.translate('xpack.snapshotRestore.restoreValidation.indicesRequiredError', { - defaultMessage: 'You must select at least one index.', + defaultMessage: 'You must select at least one data stream or index.', }) ); } @@ -93,7 +93,6 @@ export const validateRestore = (restoreSettings: RestoreSettings): RestoreValida 'xpack.snapshotRestore.restoreValidation.indexSettingsNotModifiableError', { defaultMessage: 'You can’t modify: {settings}', - // @ts-ignore Bug filed: https://github.com/elastic/kibana/issues/39299 values: { settings: unmodifiableSettings.map((setting: string, index: number) => index === 0 ? `${setting} ` : setting @@ -131,7 +130,6 @@ export const validateRestore = (restoreSettings: RestoreSettings): RestoreValida validation.errors.ignoreIndexSettings.push( i18n.translate('xpack.snapshotRestore.restoreValidation.indexSettingsNotRemovableError', { defaultMessage: 'You can’t reset: {settings}', - // @ts-ignore Bug filed: https://github.com/elastic/kibana/issues/39299 values: { settings: unremovableSettings.map((setting: string, index: number) => index === 0 ? `${setting} ` : setting diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 65c99bd71562b..7656238fee009 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -15034,14 +15034,12 @@ "xpack.snapshotRestore.policyForm.stepSettings.indicesPatternLabel": "インデックスパターン", "xpack.snapshotRestore.policyForm.stepSettings.indicesPatternPlaceholder": "logstash-* などのインデックスパターンを入力", "xpack.snapshotRestore.policyForm.stepSettings.indicesToggleCustomLink": "インデックスパターンを使用", - "xpack.snapshotRestore.policyForm.stepSettings.indicesToggleListLink": "インデックスを選択", "xpack.snapshotRestore.policyForm.stepSettings.indicesTooltip": "クラウドで管理されたポリシーにはすべてのインデックスが必要です。", "xpack.snapshotRestore.policyForm.stepSettings.partialDescription": "利用不可能なプライマリシャードのインデックスのスナップショットを許可します。これが設定されていない場合、スナップショット全体がエラーになります。", "xpack.snapshotRestore.policyForm.stepSettings.partialDescriptionTitle": "部分インデックスを許可", "xpack.snapshotRestore.policyForm.stepSettings.partialIndicesToggleSwitch": "部分インデックスを許可", "xpack.snapshotRestore.policyForm.stepSettings.policyIncludeGlobalStateLabel": "グローバルステータスを含める", "xpack.snapshotRestore.policyForm.stepSettings.selectAllIndicesLink": "すべて選択", - "xpack.snapshotRestore.policyForm.stepSettings.selectIndicesHelpText": "{count} 件の{count, plural, one {インデックス} other {インデックス}}がバックアップされます。{selectOrDeselectAllLink}", "xpack.snapshotRestore.policyForm.stepSettings.selectIndicesLabel": "インデックスを選択", "xpack.snapshotRestore.policyForm.stepSettingsTitle": "スナップショット設定", "xpack.snapshotRestore.policyList.deniedPrivilegeDescription": "スナップショットライフサイクルポリシーを管理するには、{privilegesCount, plural, one {このクラスター特権} other {これらのクラスター特権}}が必要です: {missingPrivileges}。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index bb4d4f6c36843..69d37002e538e 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -15040,14 +15040,12 @@ "xpack.snapshotRestore.policyForm.stepSettings.indicesPatternLabel": "索引模式", "xpack.snapshotRestore.policyForm.stepSettings.indicesPatternPlaceholder": "输入索引模式,例如 logstash-*", "xpack.snapshotRestore.policyForm.stepSettings.indicesToggleCustomLink": "使用索引模式", - "xpack.snapshotRestore.policyForm.stepSettings.indicesToggleListLink": "选择索引", "xpack.snapshotRestore.policyForm.stepSettings.indicesTooltip": "云托管的策略需要所有索引。", "xpack.snapshotRestore.policyForm.stepSettings.partialDescription": "允许具有不可用主分片的索引的快照。否则,整个快照将失败。", "xpack.snapshotRestore.policyForm.stepSettings.partialDescriptionTitle": "允许部分索引", "xpack.snapshotRestore.policyForm.stepSettings.partialIndicesToggleSwitch": "允许部分索引", "xpack.snapshotRestore.policyForm.stepSettings.policyIncludeGlobalStateLabel": "包括全局状态", "xpack.snapshotRestore.policyForm.stepSettings.selectAllIndicesLink": "全选", - "xpack.snapshotRestore.policyForm.stepSettings.selectIndicesHelpText": "将备份 {count} 个 {count, plural, one {索引} other {索引}}。{selectOrDeselectAllLink}", "xpack.snapshotRestore.policyForm.stepSettings.selectIndicesLabel": "选择索引", "xpack.snapshotRestore.policyForm.stepSettingsTitle": "快照设置", "xpack.snapshotRestore.policyList.deniedPrivilegeDescription": "要管理快照生命周期策略,必须具有{privilegesCount, plural, one {以下集群权限} other {以下集群权限}}:{missingPrivileges}。", From 0b15b33385c565ff90c2dc49c8d4d2485054ac25 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 1 Jul 2020 13:57:29 +0200 Subject: [PATCH 32/43] Restore updates - added spacer between title and data streams callout - added copy to the restore settings tab to indicate that settings also apply to backing indices --- .../data_streams_global_state_call_out.tsx | 3 ++- .../steps/step_logistics/step_logistics.tsx | 5 ++++- .../steps/step_settings.tsx | 20 +++++++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx index ebef440ea1bdd..64fce4dcfac43 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_global_state_call_out.tsx @@ -15,7 +15,8 @@ const i18nTexts = { callout: { title: (count: number) => i18n.translate('xpack.snapshotRestore.restoreForm.dataStreamsWarningCallOut.title', { - defaultMessage: 'This snapshot contains data {count, plural, one {stream} other {streams}}', + defaultMessage: + 'This snapshot contains {count, plural, one {a data stream} other {data streams}}', values: { count }, }), body: () => ( diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index ce0ef6ddea69f..74f049b97c742 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -176,7 +176,10 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent =
{snapshotDataStreams.length ? ( - + <> + + + ) : undefined} diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_settings.tsx index 5f3ebf804c5e1..6e6e6faac9532 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_settings.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_settings.tsx @@ -18,6 +18,7 @@ import { EuiSwitch, EuiTitle, EuiLink, + EuiCallOut, } from '@elastic/eui'; import { RestoreSettings } from '../../../../../common/types'; import { REMOVE_INDEX_SETTINGS_SUGGESTIONS } from '../../../constants'; @@ -28,10 +29,12 @@ import { StepProps } from './'; export const RestoreSnapshotStepSettings: React.FunctionComponent = ({ restoreSettings, updateRestoreSettings, + snapshotDetails, errors, }) => { const { i18n } = useServices(); const { indexSettings, ignoreIndexSettings } = restoreSettings; + const { dataStreams } = snapshotDetails; // State for index setting toggles const [isUsingIndexSettings, setIsUsingIndexSettings] = useState(Boolean(indexSettings)); @@ -96,6 +99,23 @@ export const RestoreSnapshotStepSettings: React.FunctionComponent = ( + {dataStreams?.length ? ( + <> + + + + + + ) : undefined} {/* Modify index settings */} From edadf629f696176c73507b610b28a0b29dd297d4 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 1 Jul 2020 14:05:51 +0200 Subject: [PATCH 33/43] further copy refinements --- .../steps/step_logistics/step_logistics.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index 74f049b97c742..4ff49d75c1c07 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -199,7 +199,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = description={ } @@ -400,7 +400,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = - {/* Rename indices */} + {/* Rename data streams and indices */} @@ -415,7 +415,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = description={ } fullWidth From 800161570c2f79698c760165c9d69f9a7736524c Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 1 Jul 2020 15:46:31 +0200 Subject: [PATCH 34/43] second round of copy feedback --- .../indices_and_data_streams_field.tsx | 2 +- .../components/restore_snapshot_form/steps/step_settings.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx index 435e78ca89b86..ef964bd0e3b00 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx @@ -150,7 +150,7 @@ export const IndicesAndDataStreamsField: FunctionComponent = ({ description={ } fullWidth diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_settings.tsx index 6e6e6faac9532..744f1d4d0b5a7 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_settings.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_settings.tsx @@ -111,7 +111,7 @@ export const RestoreSnapshotStepSettings: React.FunctionComponent = ( > From 04f60e1e9be296551b2e33c7b6d7abaa848a0daa Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Wed, 1 Jul 2020 18:57:05 +0200 Subject: [PATCH 35/43] fix i18n --- ...ata_streams_and_indices_list_help_text.tsx | 81 ++++++++++--------- ...ata_streams_and_indices_list_help_text.tsx | 81 ++++++++++--------- 2 files changed, 82 insertions(+), 80 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/data_streams_and_indices_list_help_text.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/data_streams_and_indices_list_help_text.tsx index 93b481f97605c..26b5752992a20 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/data_streams_and_indices_list_help_text.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/data_streams_and_indices_list_help_text.tsx @@ -21,6 +21,29 @@ export const DataStreamsAndIndicesListHelpText: FunctionComponent = ({ indices, dataStreams, }) => { + if (selectedIndicesAndDataStreams.length === 0) { + return ( + { + onSelectionChange('all'); + }} + > + + + ), + }} + /> + ); + } + const indicesCount = selectedIndicesAndDataStreams.reduce( (acc, v) => (indices.includes(v) ? acc + 1 : acc), 0 @@ -29,50 +52,28 @@ export const DataStreamsAndIndicesListHelpText: FunctionComponent = ({ (acc, v) => (dataStreams.includes(v) ? acc + 1 : acc), 0 ); - const i18nValues = { - indicesCount, - dataStreamsCount, - selectOrDeselectAllLink: - selectedIndicesAndDataStreams.length > 0 ? ( - { - onSelectionChange('none'); - }} - > - - - ) : ( - { - onSelectionChange('all'); - }} - > - - - ), - }; - if (selectedIndicesAndDataStreams.length === 0) { - return ( - - ); - } return ( { + onSelectionChange('none'); + }} + > + + + ), + }} /> ); }; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_and_indices_list_help_text.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_and_indices_list_help_text.tsx index 6f432d2468ab4..36f3c7704a569 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_and_indices_list_help_text.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/data_streams_and_indices_list_help_text.tsx @@ -21,6 +21,29 @@ export const DataStreamsAndIndicesListHelpText: FunctionComponent = ({ indices, dataStreams, }) => { + if (selectedIndicesAndDataStreams.length === 0) { + return ( + { + onSelectionChange('all'); + }} + > + + + ), + }} + /> + ); + } + const indicesCount = selectedIndicesAndDataStreams.reduce( (acc, v) => (indices.includes(v) ? acc + 1 : acc), 0 @@ -29,50 +52,28 @@ export const DataStreamsAndIndicesListHelpText: FunctionComponent = ({ (acc, v) => (dataStreams.includes(v) ? acc + 1 : acc), 0 ); - const i18nValues = { - indicesCount, - dataStreamsCount, - selectOrDeselectAllLink: - selectedIndicesAndDataStreams.length > 0 ? ( - { - onSelectionChange('none'); - }} - > - - - ) : ( - { - onSelectionChange('all'); - }} - > - - - ), - }; - if (selectedIndicesAndDataStreams.length === 0) { - return ( - - ); - } return ( { + onSelectionChange('none'); + }} + > + + + ), + }} /> ); }; From f152da9ef08bfafa456496c0d4837db867a65e1f Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 2 Jul 2020 11:32:26 +0200 Subject: [PATCH 36/43] added comment to mock --- .../__jest__/client_integration/helpers/mocks.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/mocks.tsx b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/mocks.tsx index f3d03574cd10a..fc02452e37308 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/mocks.tsx +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/mocks.tsx @@ -6,6 +6,10 @@ import React from 'react'; +/* + * Mocking AutoSizer of the react-virtualized because it does not render children in JS DOM. + * This seems related to not being able to properly discover height and width. + */ jest.mock('react-virtualized', () => { const original = jest.requireActual('react-virtualized'); From 132506c62612a6b8ffa3682b920e70092d2bde4d Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 2 Jul 2020 11:40:35 +0200 Subject: [PATCH 37/43] line spacing fixes and created issue for tracking backing index discovery in snaphots --- .../client_integration/helpers/restore_snapshot.helpers.ts | 2 +- .../__jest__/client_integration/helpers/setup_environment.tsx | 3 +++ .../common/lib/is_data_stream_backing_index.ts | 2 ++ .../collapsible_lists/collapsible_data_streams_list.tsx | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/restore_snapshot.helpers.ts b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/restore_snapshot.helpers.ts index db366f917e4a8..0cfb6fbc97975 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/restore_snapshot.helpers.ts +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/restore_snapshot.helpers.ts @@ -3,8 +3,8 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -/* eslint-disable @kbn/eslint/no-restricted-paths */ +/* eslint-disable @kbn/eslint/no-restricted-paths */ import { registerTestBed, TestBed, TestBedConfig } from '../../../../../test_utils'; import { RestoreSnapshot } from '../../../public/application/sections/restore_snapshot'; import { WithAppDependencies } from './setup_environment'; diff --git a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx index 80b990d141974..e3c0ab0be9bd2 100644 --- a/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx +++ b/x-pack/plugins/snapshot_restore/__jest__/client_integration/helpers/setup_environment.tsx @@ -64,6 +64,9 @@ export const setupEnvironment = () => { }; }; +/** + * Suppress error messages about Worker not being available in JS DOM. + */ (window as any).Worker = function Worker() { this.postMessage = () => {}; this.terminate = () => {}; diff --git a/x-pack/plugins/snapshot_restore/common/lib/is_data_stream_backing_index.ts b/x-pack/plugins/snapshot_restore/common/lib/is_data_stream_backing_index.ts index aea0de1d875e6..3b937670362f7 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/is_data_stream_backing_index.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/is_data_stream_backing_index.ts @@ -15,6 +15,8 @@ * to get this information from the snapshot itself, even though it contains the * metadata for the data stream that information is fully opaque to us until after * we have done the snapshot restore. + * + * Issue for tracking this discussion here: https://github.com/elastic/elasticsearch/issues/58890 */ export const isDataStreamBackingIndex = (indexName: string) => { return indexName.startsWith('.ds'); diff --git a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx index 4f9ef66bb598f..35a211822d2da 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx @@ -7,6 +7,7 @@ import React, { useState } from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiTitle, EuiLink, EuiIcon, EuiText, EuiSpacer } from '@elastic/eui'; + interface Props { dataStreams: string[] | string | undefined; } From d2551b88209576d5d76ce983576bd0963025bb7f Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 2 Jul 2020 12:37:21 +0200 Subject: [PATCH 38/43] refactor collapsible list logic and tests --- .../snapshot_restore/common/lib/index.ts | 2 +- .../common/lib/snapshot_serialization.ts | 4 +- .../snapshot_restore/common/lib/utils.ts | 2 +- .../collapsible_data_streams_list.tsx | 105 ++++++++---------- .../collapsible_indices_list.tsx | 104 ++++++++--------- .../use_collapsible_list.test.ts | 29 +++++ .../collapsible_lists/use_collapsible_list.ts | 42 +++++++ .../steps/step_logistics/step_logistics.tsx | 4 +- 8 files changed, 171 insertions(+), 121 deletions(-) create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/use_collapsible_list.test.ts create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/use_collapsible_list.ts diff --git a/x-pack/plugins/snapshot_restore/common/lib/index.ts b/x-pack/plugins/snapshot_restore/common/lib/index.ts index 2e7ca8f3e12cd..eaec8054a93ab 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/index.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/index.ts @@ -16,5 +16,5 @@ export { serializeSnapshotRetention, } from './snapshot_serialization'; export { deserializePolicy, serializePolicy } from './policy_serialization'; -export { indicesToArray } from './utils'; +export { csvToArray } from './utils'; export { isDataStreamBackingIndex } from './is_data_stream_backing_index'; diff --git a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts index 06bf7fbc0d967..a85b49430eecd 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/snapshot_serialization.ts @@ -17,7 +17,7 @@ import { import { deserializeTime, serializeTime } from './time_serialization'; -import { indicesToArray } from './utils'; +import { csvToArray } from './utils'; export function deserializeSnapshotDetails( repository: string, @@ -131,7 +131,7 @@ export function deserializeSnapshotConfig(snapshotConfigEs: SnapshotConfigEs): S export function serializeSnapshotConfig(snapshotConfig: SnapshotConfig): SnapshotConfigEs { const { indices, ignoreUnavailable, includeGlobalState, partial, metadata } = snapshotConfig; - const indicesArray = indicesToArray(indices); + const indicesArray = csvToArray(indices); const snapshotConfigEs: SnapshotConfigEs = { indices: indicesArray, diff --git a/x-pack/plugins/snapshot_restore/common/lib/utils.ts b/x-pack/plugins/snapshot_restore/common/lib/utils.ts index fb35f59f8b973..96eb7cb6908d8 100644 --- a/x-pack/plugins/snapshot_restore/common/lib/utils.ts +++ b/x-pack/plugins/snapshot_restore/common/lib/utils.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -export const indicesToArray = (indices?: string | string[]): string[] => { +export const csvToArray = (indices?: string | string[]): string[] => { return indices && Array.isArray(indices) ? indices : typeof indices === 'string' diff --git a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx index 35a211822d2da..ce1bd7c8d6e45 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_data_streams_list.tsx @@ -4,75 +4,64 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState } from 'react'; +import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiTitle, EuiLink, EuiIcon, EuiText, EuiSpacer } from '@elastic/eui'; +import { useCollapsibleList } from './use_collapsible_list'; + interface Props { dataStreams: string[] | string | undefined; } export const CollapsibleDataStreamsList: React.FunctionComponent = ({ dataStreams }) => { - const [isShowingFullDataStreamsList, setIsShowingFullDataStreamsList] = useState(false); - const displayDataStreams = dataStreams - ? typeof dataStreams === 'string' - ? dataStreams.split(',') - : dataStreams - : undefined; - const hiddenDataStreams = - displayDataStreams && displayDataStreams.length > 10 ? displayDataStreams.length - 10 : 0; - return ( + const { isShowingFullList, setIsShowingFullList, items, hiddenItemsCount } = useCollapsibleList({ + items: dataStreams, + }); + + return items === 'all' ? ( + + ) : ( <> - {displayDataStreams ? ( + +
    + {items.map((dataStream) => ( +
  • + + {dataStream} + +
  • + ))} +
+
+ {hiddenItemsCount ? ( <> - -
    - {(isShowingFullDataStreamsList - ? displayDataStreams - : [...displayDataStreams].splice(0, 10) - ).map((dataStream) => ( -
  • - - {dataStream} - -
  • - ))} -
-
- {hiddenDataStreams ? ( - <> - - - isShowingFullDataStreamsList - ? setIsShowingFullDataStreamsList(false) - : setIsShowingFullDataStreamsList(true) - } - > - {isShowingFullDataStreamsList ? ( - - ) : ( - - )}{' '} - - - - ) : null} + + + isShowingFullList ? setIsShowingFullList(false) : setIsShowingFullList(true) + } + > + {isShowingFullList ? ( + + ) : ( + + )}{' '} + + - ) : ( - - )} + ) : null} ); }; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_indices_list.tsx b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_indices_list.tsx index 1d8ee726f4cc7..ff676a3696941 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_indices_list.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/collapsible_indices_list.tsx @@ -4,73 +4,63 @@ * you may not use this file except in compliance with the Elastic License. */ -import React, { useState } from 'react'; +import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiTitle, EuiLink, EuiIcon, EuiText, EuiSpacer } from '@elastic/eui'; + +import { useCollapsibleList } from './use_collapsible_list'; + interface Props { indices: string[] | string | undefined; } export const CollapsibleIndicesList: React.FunctionComponent = ({ indices }) => { - const [isShowingFullIndicesList, setIsShowingFullIndicesList] = useState(false); - const displayIndices = indices - ? typeof indices === 'string' - ? indices.split(',') - : indices - : undefined; - const hiddenIndicesCount = - displayIndices && displayIndices.length > 10 ? displayIndices.length - 10 : 0; - return ( + const { hiddenItemsCount, isShowingFullList, items, setIsShowingFullList } = useCollapsibleList({ + items: indices, + }); + return items === 'all' ? ( + + ) : ( <> - {displayIndices ? ( + +
    + {items.map((index) => ( +
  • + + {index} + +
  • + ))} +
+
+ {hiddenItemsCount ? ( <> - -
    - {(isShowingFullIndicesList ? displayIndices : [...displayIndices].splice(0, 10)).map( - (index) => ( -
  • - - {index} - -
  • - ) - )} -
-
- {hiddenIndicesCount ? ( - <> - - - isShowingFullIndicesList - ? setIsShowingFullIndicesList(false) - : setIsShowingFullIndicesList(true) - } - > - {isShowingFullIndicesList ? ( - - ) : ( - - )}{' '} - - - - ) : null} + + + isShowingFullList ? setIsShowingFullList(false) : setIsShowingFullList(true) + } + > + {isShowingFullList ? ( + + ) : ( + + )}{' '} + + - ) : ( - - )} + ) : null} ); }; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/use_collapsible_list.test.ts b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/use_collapsible_list.test.ts new file mode 100644 index 0000000000000..bdeb801117de9 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/use_collapsible_list.test.ts @@ -0,0 +1,29 @@ +/* + * 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 { renderHook } from '@testing-library/react-hooks'; + +import { useCollapsibleList } from './use_collapsible_list'; + +describe('useCollapseList', () => { + it('handles undefined', () => { + const { result } = renderHook(() => useCollapsibleList({ items: undefined })); + expect(result.current.items).toBe('all'); + expect(result.current.hiddenItemsCount).toBe(0); + }); + + it('handles csv', () => { + const { result } = renderHook(() => useCollapsibleList({ items: 'a,b,c' })); + expect(result.current.items).toEqual(['a', 'b', 'c']); + expect(result.current.hiddenItemsCount).toBe(0); + }); + + it('hides items passed a defined maximum (10)', () => { + const items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']; + const { result } = renderHook(() => useCollapsibleList({ items })); + expect(result.current.items).toEqual(items.slice(0, -1)); + expect(result.current.hiddenItemsCount).toBe(1); + }); +}); diff --git a/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/use_collapsible_list.ts b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/use_collapsible_list.ts new file mode 100644 index 0000000000000..275915c5760af --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/collapsible_lists/use_collapsible_list.ts @@ -0,0 +1,42 @@ +/* + * 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 { useState } from 'react'; +import { csvToArray } from '../../../../common/lib'; + +type ChildItems = string[] | 'all'; + +interface Arg { + items: string[] | string | undefined; +} + +export interface ReturnValue { + items: ChildItems; + hiddenItemsCount: number; + isShowingFullList: boolean; + setIsShowingFullList: (showAll: boolean) => void; +} + +const maximumItemPreviewCount = 10; + +export const useCollapsibleList = ({ items }: Arg): ReturnValue => { + const [isShowingFullList, setIsShowingFullList] = useState(false); + const itemsArray = csvToArray(items); + const displayItems: ChildItems = + items === undefined + ? 'all' + : itemsArray.slice(0, isShowingFullList ? Infinity : maximumItemPreviewCount); + + const hiddenItemsCount = + itemsArray.length > maximumItemPreviewCount ? itemsArray.length - maximumItemPreviewCount : 0; + + return { + items: displayItems, + hiddenItemsCount, + setIsShowingFullList, + isShowingFullList, + }; +}; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index 4ff49d75c1c07..496523a80da75 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -22,7 +22,7 @@ import { } from '@elastic/eui'; import { EuiSelectableOption } from '@elastic/eui'; -import { indicesToArray, isDataStreamBackingIndex } from '../../../../../../common/lib'; +import { csvToArray, isDataStreamBackingIndex } from '../../../../../../common/lib'; import { RestoreSettings } from '../../../../../../common/types'; import { documentationLinksService } from '../../../../services/documentation'; @@ -310,7 +310,7 @@ export const RestoreSnapshotStepLogistics: React.FunctionComponent = }); } }} - selectedIndicesAndDataStreams={indicesToArray(restoreIndices)} + selectedIndicesAndDataStreams={csvToArray(restoreIndices)} indices={snapshotIndices} dataStreams={snapshotDataStreams} /> From ab8719d73b6370c595c2a75ef2569828ad52def8 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 2 Jul 2020 12:40:42 +0200 Subject: [PATCH 39/43] refactor editing managed policy check --- .../application/components/policy_form/policy_form.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx index cb9ecda787cfc..3e1fb9b6500b3 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/policy_form.tsx @@ -73,6 +73,8 @@ export const PolicyForm: React.FunctionComponent = ({ }, }); + const isEditingManagedPolicy = Boolean(isEditing && policy.isManagedPolicy); + // Policy validation state const [validation, setValidation] = useState({ isValid: true, @@ -187,8 +189,8 @@ export const PolicyForm: React.FunctionComponent = ({ {currentStep === lastStep ? ( savePolicy()} isLoading={isSaving} From 7d2feee640620fec8c2bec8159395aa65eda0158 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 2 Jul 2020 12:45:32 +0200 Subject: [PATCH 40/43] refactor copy to be clearer about pluralisation of data streams --- .../data_streams_and_indices_list_help_text.tsx | 2 +- .../step_logistics/data_streams_and_indices_list_help_text.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/data_streams_and_indices_list_help_text.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/data_streams_and_indices_list_help_text.tsx index 26b5752992a20..3570c74fb8fd0 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/data_streams_and_indices_list_help_text.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/data_streams_and_indices_list_help_text.tsx @@ -56,7 +56,7 @@ export const DataStreamsAndIndicesListHelpText: FunctionComponent = ({ return ( = ({ return ( Date: Thu, 2 Jul 2020 12:50:49 +0200 Subject: [PATCH 41/43] refactor file structure in components for data stream badge --- .../application/components/{shared => }/data_stream_badge.tsx | 0 .../public/application/components/{shared => lib}/helpers.ts | 0 .../public/application/components/{shared => lib}/index.ts | 2 -- .../fields/indices_and_data_streams_field/helpers.tsx | 3 ++- .../indices_and_data_streams_field.tsx | 3 ++- .../steps/step_logistics/step_logistics.tsx | 3 ++- 6 files changed, 6 insertions(+), 5 deletions(-) rename x-pack/plugins/snapshot_restore/public/application/components/{shared => }/data_stream_badge.tsx (100%) rename x-pack/plugins/snapshot_restore/public/application/components/{shared => lib}/helpers.ts (100%) rename x-pack/plugins/snapshot_restore/public/application/components/{shared => lib}/index.ts (84%) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/shared/data_stream_badge.tsx b/x-pack/plugins/snapshot_restore/public/application/components/data_stream_badge.tsx similarity index 100% rename from x-pack/plugins/snapshot_restore/public/application/components/shared/data_stream_badge.tsx rename to x-pack/plugins/snapshot_restore/public/application/components/data_stream_badge.tsx diff --git a/x-pack/plugins/snapshot_restore/public/application/components/shared/helpers.ts b/x-pack/plugins/snapshot_restore/public/application/components/lib/helpers.ts similarity index 100% rename from x-pack/plugins/snapshot_restore/public/application/components/shared/helpers.ts rename to x-pack/plugins/snapshot_restore/public/application/components/lib/helpers.ts diff --git a/x-pack/plugins/snapshot_restore/public/application/components/shared/index.ts b/x-pack/plugins/snapshot_restore/public/application/components/lib/index.ts similarity index 84% rename from x-pack/plugins/snapshot_restore/public/application/components/shared/index.ts rename to x-pack/plugins/snapshot_restore/public/application/components/lib/index.ts index 8d1695ec403ed..a40695e9a20e8 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/shared/index.ts +++ b/x-pack/plugins/snapshot_restore/public/application/components/lib/index.ts @@ -4,6 +4,4 @@ * you may not use this file except in compliance with the Elastic License. */ -export { DataStreamBadge } from './data_stream_badge'; - export { orderDataStreamsAndIndices } from './helpers'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx index 465aa20f3fd88..b910dffb90460 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx @@ -6,7 +6,8 @@ import React from 'react'; import { EuiSelectableOption } from '@elastic/eui'; -import { DataStreamBadge, orderDataStreamsAndIndices } from '../../../../../shared'; +import { orderDataStreamsAndIndices } from '../../../../../lib'; +import { DataStreamBadge } from '../../../../../data_stream_badge'; export const mapSelectionToIndicesOptions = ({ allSelected, diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx index ef964bd0e3b00..8f4fa65205476 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx @@ -27,7 +27,8 @@ import { SlmPolicyPayload } from '../../../../../../../../common/types'; import { useServices } from '../../../../../../app_context'; import { PolicyValidation } from '../../../../../../services/validation'; -import { orderDataStreamsAndIndices, DataStreamBadge } from '../../../../../shared'; +import { orderDataStreamsAndIndices } from '../../../../../lib'; +import { DataStreamBadge } from '../../../../../data_stream_badge'; import { mapSelectionToIndicesOptions, determineListMode } from './helpers'; diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx index 496523a80da75..d9fd4cca0d614 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_logistics/step_logistics.tsx @@ -29,7 +29,8 @@ import { documentationLinksService } from '../../../../services/documentation'; import { useServices } from '../../../../app_context'; -import { orderDataStreamsAndIndices, DataStreamBadge } from '../../../shared'; +import { orderDataStreamsAndIndices } from '../../../lib'; +import { DataStreamBadge } from '../../../data_stream_badge'; import { StepProps } from '../index'; From 2fd876fd38a593e5278b891c6bec739cc316fe1a Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 2 Jul 2020 13:08:56 +0200 Subject: [PATCH 42/43] added tests for indices and data streams field helper --- .../helpers.test.ts | 69 +++++++++++++++++++ .../helpers.tsx | 8 +-- 2 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.test.ts diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.test.ts b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.test.ts new file mode 100644 index 0000000000000..9bf97af6400b5 --- /dev/null +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.test.ts @@ -0,0 +1,69 @@ +/* + * 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 { determineListMode } from './helpers'; + +describe('helpers', () => { + describe('determineListMode', () => { + test('list length (> 100)', () => { + expect( + determineListMode({ + indices: Array.from(Array(101).keys()).map(String), + dataStreams: [], + configuredIndices: undefined, + }) + ).toBe('custom'); + + // The length of indices and data streams are cumulative + expect( + determineListMode({ + indices: Array.from(Array(51).keys()).map(String), + dataStreams: Array.from(Array(51).keys()).map(String), + configuredIndices: undefined, + }) + ).toBe('custom'); + + // Other values should result in list mode + expect( + determineListMode({ + indices: [], + dataStreams: [], + configuredIndices: undefined, + }) + ).toBe('list'); + }); + + test('configured indices is a string', () => { + expect( + determineListMode({ + indices: [], + dataStreams: [], + configuredIndices: 'test', + }) + ).toBe('custom'); + }); + + test('configured indices not included in current indices and data streams', () => { + expect( + determineListMode({ + indices: ['a'], + dataStreams: ['b'], + configuredIndices: ['a', 'b', 'c'], + }) + ).toBe('custom'); + }); + + test('configured indices included in current indices and data streams', () => { + expect( + determineListMode({ + indices: ['a'], + dataStreams: ['b'], + configuredIndices: ['a', 'b'], + }) + ).toBe('list'); + }); + }); +}); diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx index b910dffb90460..98ad2fe9c5489 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/helpers.tsx @@ -58,11 +58,11 @@ export const determineListMode = ({ }): 'custom' | 'list' => { const indicesAndDataStreams = indices.concat(dataStreams); return typeof configuredIndices === 'string' || + indicesAndDataStreams.length > 100 || (Array.isArray(configuredIndices) && - (indices.length > 100 || - // If not every past configured index maps to an existing index or data stream - // we also show the custom list - !configuredIndices.every((c) => indicesAndDataStreams.some((i) => i === c)))) + // If not every past configured index maps to an existing index or data stream + // we also show the custom list + !configuredIndices.every((c) => indicesAndDataStreams.some((i) => i === c))) ? 'custom' : 'list'; }; From 2e46e93b0968c7bd4e7b438a16dcb4dbfd58d08f Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Thu, 2 Jul 2020 13:18:11 +0200 Subject: [PATCH 43/43] refactored types and fixed i18n id per guidelines --- .../indices_and_data_streams_field.tsx | 2 +- .../restore_snapshot_form/steps/step_settings.tsx | 2 +- x-pack/plugins/snapshot_restore/server/types.ts | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx index 8f4fa65205476..94854905e6686 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/policy_form/steps/step_settings/fields/indices_and_data_streams_field/indices_and_data_streams_field.tsx @@ -44,7 +44,7 @@ interface Props { } /** - * In future we may be able to split data streams to it's own field, but for now + * In future we may be able to split data streams to its own field, but for now * they share an array "indices" in the snapshot lifecycle policy config. See * this github issue for progress: https://github.com/elastic/elasticsearch/issues/58474 */ diff --git a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_settings.tsx b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_settings.tsx index 744f1d4d0b5a7..b9a2d7e4b7cd9 100644 --- a/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_settings.tsx +++ b/x-pack/plugins/snapshot_restore/public/application/components/restore_snapshot_form/steps/step_settings.tsx @@ -110,7 +110,7 @@ export const RestoreSnapshotStepSettings: React.FunctionComponent = ( )} > diff --git a/x-pack/plugins/snapshot_restore/server/types.ts b/x-pack/plugins/snapshot_restore/server/types.ts index 76163655b45d5..8cfcaec1a2cd1 100644 --- a/x-pack/plugins/snapshot_restore/server/types.ts +++ b/x-pack/plugins/snapshot_restore/server/types.ts @@ -34,7 +34,7 @@ export interface RouteDependencies { /** * An object representing a resolved index, data stream or alias */ -interface DataObjectFromES { +interface IndexAndAliasFromEs { name: string; // per https://github.com/elastic/elasticsearch/pull/57626 attributes: Array<'open' | 'closed' | 'hidden' | 'frozen'>; @@ -42,8 +42,8 @@ interface DataObjectFromES { } export interface ResolveIndexResponseFromES { - indices: DataObjectFromES[]; - aliases: DataObjectFromES[]; + indices: IndexAndAliasFromEs[]; + aliases: IndexAndAliasFromEs[]; data_streams: Array<{ name: string; backing_indices: string[]; timestamp_field: string }>; }