From f201626b4feb1039f465f8d6a2c1a39fd63ac71a Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 2 Mar 2021 18:12:13 +0100 Subject: [PATCH] [ILM] Allow multiple searchable snapshot actions (#92789) (#93241) * remove logic that disables SS action in cold if no rollover and always show replicas field * update test coverage to be consistent with new form behaviour and expand hot phase without rollover test * only licensing can disable searchable snapshot field * clean up i18n * remove ss field callout * update error reporting logic to include causes chain, also update UI to show causes * updated searchable snapshot field in hot phase callout Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../errors/es_error_parser.ts | 6 ++--- .../errors/handle_es_error.ts | 11 +++++++- .../searchable_snapshot_field.tsx | 27 ++++--------------- .../public/application/services/api_errors.ts | 5 +++- .../translations/translations/ja-JP.json | 2 -- .../translations/translations/zh-CN.json | 2 -- 6 files changed, 22 insertions(+), 31 deletions(-) diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/es_error_parser.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/es_error_parser.ts index 61a8882317f9f..fc400e4a87b3a 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/es_error_parser.ts +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/es_error_parser.ts @@ -11,14 +11,14 @@ interface ParsedError { cause: string[]; } -const getCause = (obj: any = {}, causes: string[] = []): string[] => { +export const getEsCause = (obj: any = {}, causes: string[] = []): string[] => { const updated = [...causes]; if (obj.caused_by) { updated.push(obj.caused_by.reason); // Recursively find all the "caused by" reasons - return getCause(obj.caused_by, updated); + return getEsCause(obj.caused_by, updated); } return updated.filter(Boolean); @@ -27,7 +27,7 @@ const getCause = (obj: any = {}, causes: string[] = []): string[] => { export const parseEsError = (err: string): ParsedError => { try { const { error } = JSON.parse(err); - const cause = getCause(error); + const cause = getEsCause(error); return { message: error.reason, cause, diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts index 4a45cff0b9604..a98a74375638d 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts @@ -9,6 +9,7 @@ import { ApiError } from '@elastic/elasticsearch'; import { ResponseError } from '@elastic/elasticsearch/lib/errors'; import { IKibanaResponse, KibanaResponseFactory } from 'kibana/server'; +import { getEsCause } from './es_error_parser'; interface EsErrorHandlerParams { error: ApiError; @@ -34,7 +35,15 @@ export const handleEsError = ({ const { statusCode, body } = error as ResponseError; return response.customError({ statusCode, - body: { message: body.error?.reason }, + body: { + message: body.error?.reason, + attributes: { + // The full original ES error object + error: body.error, + // We assume that this is an ES error object with a nested caused by chain if we can see the "caused_by" field at the top-level + causes: body.error?.caused_by ? getEsCause(body.error) : undefined, + }, + }, }); } // Case: default diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx index 1a78149521e63..3fc7064575555 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx @@ -61,9 +61,6 @@ export const SearchableSnapshotField: FunctionComponent = ({ phase }) => const isColdPhase = phase === 'cold'; const isDisabledDueToLicense = !license.canUseSearchableSnapshot(); - const isDisabledInColdDueToHotPhase = isColdPhase && isUsingSearchableSnapshotInHotPhase; - - const isDisabled = isDisabledDueToLicense || isDisabledInColdDueToHotPhase; const [isFieldToggleChecked, setIsFieldToggleChecked] = useState(() => Boolean( @@ -74,10 +71,10 @@ export const SearchableSnapshotField: FunctionComponent = ({ phase }) => ); useEffect(() => { - if (isDisabled) { + if (isDisabledDueToLicense) { setIsFieldToggleChecked(false); } - }, [isDisabled]); + }, [isDisabledDueToLicense]); const renderField = () => ( @@ -254,7 +251,7 @@ export const SearchableSnapshotField: FunctionComponent = ({ phase }) => 'xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotCalloutBody', { defaultMessage: - 'Force merge, shrink, freeze and cold phase searchable snapshots are not allowed when searchable snapshots are enabled in the hot phase.', + 'Force merge, shrink and freeze actions are not allowed when searchable snapshots are enabled in this phase.', } )} data-test-subj="searchableSnapshotFieldsDisabledCallout" @@ -278,20 +275,6 @@ export const SearchableSnapshotField: FunctionComponent = ({ phase }) => )} ); - } else if (isDisabledInColdDueToHotPhase) { - infoCallout = ( - - ); } return infoCallout ? ( @@ -308,7 +291,7 @@ export const SearchableSnapshotField: FunctionComponent = ({ phase }) => data-test-subj={`searchableSnapshotField-${phase}`} switchProps={{ checked: isFieldToggleChecked, - disabled: isDisabled, + disabled: isDisabledDueToLicense, onChange: setIsFieldToggleChecked, 'data-test-subj': 'searchableSnapshotToggle', label: i18n.translate( @@ -339,7 +322,7 @@ export const SearchableSnapshotField: FunctionComponent = ({ phase }) => fieldNotices={renderInfoCallout()} fullWidth > - {isDisabled ?
: renderField} + {isDisabledDueToLicense ?
: renderField} ); }; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.ts index 54ef91457b1f9..fc37b62e30eb2 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/api_errors.ts @@ -11,7 +11,10 @@ import { fatalErrors, toasts } from './notification'; function createToastConfig(error: IHttpFetchError, errorTitle: string) { if (error && error.body) { // Error body shape is defined by the API. - const { error: errorString, statusCode, message } = error.body; + const { error: errorString, statusCode, message: errorMessage, attributes } = error.body; + const message = attributes?.causes?.length + ? attributes.causes[attributes.causes.length - 1] + : errorMessage; return { title: errorTitle, diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 88ac1934d167f..dd438da1d80d5 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -9456,8 +9456,6 @@ "xpack.indexLifecycleMgmt.editPolicy.saveAsNewPolicyMessage": "新規ポリシーとして保存します", "xpack.indexLifecycleMgmt.editPolicy.saveButton": "ポリシーを保存", "xpack.indexLifecycleMgmt.editPolicy.saveErrorMessage": "ライフサイクルポリシー {lifecycleName} の保存中にエラーが発生しました", - "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotCalloutBody": "検索可能なスナップショットがホットフェーズで有効な場合には、強制、マージ、縮小、凍結、コールドフェーズの検索可能なスナップショットは許可されません。", - "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotDisabledCalloutBody": "ホットフェーズで構成されているときには、コールドフェーズで検索可能なスナップショットを作成できません。", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotFieldDescription": "選択したリポジトリで管理されたインデックスのスナップショットを作成し、検索可能なスナップショットとしてマウントします。{learnMoreLink}。", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotFieldLabel": "検索可能なスナップショットリポジドリ", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotFieldTitle": "検索可能スナップショット", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 51cde6c1aae37..391b1f68086d4 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -9480,8 +9480,6 @@ "xpack.indexLifecycleMgmt.editPolicy.saveAsNewPolicyMessage": "另存为新策略", "xpack.indexLifecycleMgmt.editPolicy.saveButton": "保存策略", "xpack.indexLifecycleMgmt.editPolicy.saveErrorMessage": "保存生命周期策略 {lifecycleName} 时出错", - "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotCalloutBody": "在热阶段启用可搜索快照时,不允许强制合并、缩小、冻结可搜索快照以及将其置入冷阶段。", - "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotDisabledCalloutBody": "无法在冷阶段创建在热阶段配置的可搜索快照。", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotFieldDescription": "在所选存储库中拍取受管索引的快照,并将其安装为可搜索快照。{learnMoreLink}。", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotFieldLabel": "可搜索快照存储库", "xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotFieldTitle": "可搜索快照",