diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 3a15fc6bf2706..10ffbcd5809a8 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -26423,18 +26423,12 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.runReindexLabel": "再インデックスの開始", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.tryAgainLabel": "再試行", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexDescription": "再インデックス中はインデックスが読み取り専用です。再インデックスが完了するまでは、ドキュメントの追加、更新、削除ができません。新しいクラスターを再インデックスする必要がある場合は、再インデックスAPIを使用します。{docsLink}", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.aliasSwapStepTitle": "元のインデックスをエイリアスと交換します。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelButton.cancelLabel": "キャンセル", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelButton.cancelledLabel": "キャンセル済み", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelButton.cancellingLabel": "キャンセル中…", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelButton.errorLabel": "キャンセルできませんでした", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelledTitle": "再インデックスはキャンセルされました。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.createIndexStepTitle": "新しいインデックスを作成します。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.inProgress.aliasSwapStepTitle": "元のインデックスをエイリアスと交換しています。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.inProgress.createIndexStepTitle": "新しいインデックスを作成しています。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.inProgress.readonlyStepTitle": "元のインデックスを読み取り専用に設定しています。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.inProgress.reindexingDocumentsStepTitle": "ドキュメントを再インデックスしています。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.readonlyStepTitle": "元のインデックスを読み取り専用に設定します。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.reindexingDocumentsStepTitle": "ドキュメントのインデックスを作成します。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklistTitle": "プロセスを再インデックス中", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingFailedCalloutTitle": "再インデックスエラー", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 987a9bfc27f80..eaa6c6f1d9abd 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -26878,18 +26878,12 @@ "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.runReindexLabel": "启动重新索引", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexButton.tryAgainLabel": "重试", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexDescription": "重新索引期间,索引将处于只读状态。在重新索引完成之前,您无法添加、更新或删除文档。如果需要重新索引到新集群,请使用重新索引 API。{docsLink}", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.aliasSwapStepTitle": "交换具有别名的原始索引。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelButton.cancelLabel": "取消", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelButton.cancelledLabel": "已取消", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelButton.cancellingLabel": "正在取消……", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelButton.errorLabel": "无法取消", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.cancelledTitle": "重新索引已取消。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.createIndexStepTitle": "创建新索引。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.inProgress.aliasSwapStepTitle": "正在交换具有别名的原始索引。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.inProgress.createIndexStepTitle": "正在创建新索引。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.inProgress.readonlyStepTitle": "正在将原始索引设置为只读。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.inProgress.reindexingDocumentsStepTitle": "正在重新索引文档。", - "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.readonlyStepTitle": "将原始索引设置为只读。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklist.reindexingDocumentsStepTitle": "索引文档。", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingChecklistTitle": "重新索引过程", "xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingFailedCalloutTitle": "重新索引错误", diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts index fdd8a1c993937..5566ec1d17e2b 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/default_deprecation_flyout.test.ts @@ -27,6 +27,16 @@ describe('Default deprecation flyout', () => { jobId: MOCK_JOB_ID, status: 'idle', }); + httpRequestsMockHelpers.setReindexStatusResponse({ + reindexOp: null, + warnings: [], + hasRequiredPrivileges: true, + meta: { + indexName: 'foo', + reindexName: 'reindexed-foo', + aliases: [], + }, + }); await act(async () => { testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts index 3b8a756b8e64c..49c084eb9f27d 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/deprecations_list.test.ts @@ -34,6 +34,16 @@ describe('ES deprecations table', () => { jobId: MOCK_JOB_ID, status: 'idle', }); + httpRequestsMockHelpers.setReindexStatusResponse({ + reindexOp: null, + warnings: [], + hasRequiredPrivileges: true, + meta: { + indexName: 'foo', + reindexName: 'reindexed-foo', + aliases: [], + }, + }); await act(async () => { testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts index f62d24081ed56..f032c34040bfe 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/index_settings_deprecation_flyout.test.ts @@ -28,6 +28,16 @@ describe('Index settings deprecation flyout', () => { jobId: MOCK_JOB_ID, status: 'idle', }); + httpRequestsMockHelpers.setReindexStatusResponse({ + reindexOp: null, + warnings: [], + hasRequiredPrivileges: true, + meta: { + indexName: 'foo', + reindexName: 'reindexed-foo', + aliases: [], + }, + }); await act(async () => { testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts index b24cd5a69a28e..11bb27bb8b331 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/ml_snapshots_deprecation_flyout.test.ts @@ -30,6 +30,16 @@ describe('Machine learning deprecation flyout', () => { jobId: MOCK_JOB_ID, status: 'idle', }); + httpRequestsMockHelpers.setReindexStatusResponse({ + reindexOp: null, + warnings: [], + hasRequiredPrivileges: true, + meta: { + indexName: 'foo', + reindexName: 'reindexed-foo', + aliases: [], + }, + }); await act(async () => { testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); diff --git a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts index 3c6fe0e5f5329..25742958aa243 100644 --- a/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts +++ b/x-pack/plugins/upgrade_assistant/__jest__/client_integration/es_deprecations/reindex_deprecation_flyout.test.ts @@ -7,17 +7,28 @@ import { act } from 'react-dom/test-utils'; +import { ReindexStatus, ReindexStep, ReindexStatusResponse } from '../../../common/types'; import { setupEnvironment } from '../helpers'; import { ElasticsearchTestBed, setupElasticsearchPage } from './es_deprecations.helpers'; import { esDeprecationsMockResponse, MOCK_SNAPSHOT_ID, MOCK_JOB_ID } from './mocked_responses'; -import { ReindexStatus, ReindexStep } from '../../../common/types'; + +const defaultReindexStatusMeta: ReindexStatusResponse['meta'] = { + indexName: 'foo', + reindexName: 'reindexed-foo', + aliases: [], +}; // Note: The reindexing flyout UX is subject to change; more tests should be added here once functionality is built out describe('Reindex deprecation flyout', () => { let testBed: ElasticsearchTestBed; const { server, httpRequestsMockHelpers } = setupEnvironment(); + beforeAll(() => { + jest.useFakeTimers(); + }); + afterAll(() => { + jest.useRealTimers(); server.restore(); }); @@ -29,6 +40,16 @@ describe('Reindex deprecation flyout', () => { jobId: MOCK_JOB_ID, status: 'idle', }); + httpRequestsMockHelpers.setReindexStatusResponse({ + reindexOp: null, + warnings: [], + hasRequiredPrivileges: true, + meta: { + indexName: 'foo', + reindexName: 'reindexed-foo', + aliases: [], + }, + }); await act(async () => { testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); @@ -54,6 +75,7 @@ describe('Reindex deprecation flyout', () => { reindexOp: null, warnings: [], hasRequiredPrivileges: true, + meta: defaultReindexStatusMeta, }); await act(async () => { @@ -113,6 +135,7 @@ describe('Reindex deprecation flyout', () => { }, warnings: [], hasRequiredPrivileges: true, + meta: defaultReindexStatusMeta, }); await act(async () => { @@ -137,6 +160,7 @@ describe('Reindex deprecation flyout', () => { }, warnings: [], hasRequiredPrivileges: true, + meta: defaultReindexStatusMeta, }); await act(async () => { @@ -148,7 +172,7 @@ describe('Reindex deprecation flyout', () => { await actions.table.clickDeprecationRowAt('reindex', 0); - expect(find('reindexChecklistTitle').text()).toEqual('Reindexing in progress… 31%'); + expect(find('reindexChecklistTitle').text()).toEqual('Reindexing in progress… 30%'); expect(exists('cancelReindexingDocumentsButton')).toBe(true); }); @@ -161,6 +185,7 @@ describe('Reindex deprecation flyout', () => { }, warnings: [], hasRequiredPrivileges: true, + meta: defaultReindexStatusMeta, }); await act(async () => { @@ -172,7 +197,7 @@ describe('Reindex deprecation flyout', () => { await actions.table.clickDeprecationRowAt('reindex', 0); - expect(find('reindexChecklistTitle').text()).toEqual('Reindexing in progress… 95%'); + expect(find('reindexChecklistTitle').text()).toEqual('Reindexing in progress… 90%'); expect(exists('cancelReindexingDocumentsButton')).toBe(false); }); @@ -185,19 +210,30 @@ describe('Reindex deprecation flyout', () => { }, warnings: [], hasRequiredPrivileges: true, + meta: defaultReindexStatusMeta, }); await act(async () => { testBed = await setupElasticsearchPage({ isReadOnlyMode: false }); }); - testBed.component.update(); - const { actions, find, exists } = testBed; + const { actions, find, exists, component } = testBed; + component.update(); await actions.table.clickDeprecationRowAt('reindex', 0); - expect(find('reindexChecklistTitle').text()).toEqual('Reindexing process'); + expect(find('reindexChecklistTitle').text()).toEqual('Reindexing in progress… 95%'); expect(exists('cancelReindexingDocumentsButton')).toBe(false); + + // We have put in place a "fake" fifth step to delete the original index + // In reality that was done in the last step (when the alias was created), + // but for the user we will display it as a separate reindex step + await act(async () => { + jest.advanceTimersByTime(1000); + }); + component.update(); + + expect(find('reindexChecklistTitle').text()).toEqual('Reindexing process'); }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index 89afa05dfe222..02e8880d117f1 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -28,6 +28,8 @@ export enum ReindexStep { reindexStarted = 40, reindexCompleted = 50, aliasCreated = 60, + originalIndexDeleted = 70, + existingAliasesUpdated = 80, } export enum ReindexStatus { @@ -41,7 +43,20 @@ export enum ReindexStatus { fetchFailed, } +export interface ReindexStatusResponse { + meta: { + indexName: string; + reindexName: string; + // Array of aliases pointing to the index being reindexed + aliases: string[]; + }; + warnings?: ReindexWarning[]; + reindexOp?: ReindexOperation; + hasRequiredPrivileges?: boolean; +} + export const REINDEX_OP_TYPE = 'upgrade-assistant-reindex-operation'; + export interface QueueSettings extends SavedObjectAttributes { /** * A Unix timestamp of when the reindex operation was enqueued. @@ -106,7 +121,8 @@ export interface ReindexOperation extends SavedObjectAttributes { export type ReindexSavedObject = SavedObject; // 7.0 -> 8.0 warnings -export type ReindexWarningTypes = 'customTypeName' | 'indexSetting'; +export type ReindexWarningTypes = 'customTypeName' | 'indexSetting' | 'replaceIndexWithAlias'; + export interface ReindexWarning { warningType: ReindexWarningTypes; /** diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/context.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/context.tsx index 2d34253d2c426..3d4459e7380b7 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/context.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/context.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useEffect, createContext, useContext } from 'react'; +import React, { createContext, useContext } from 'react'; import { ApiService } from '../../../../lib/api'; import { useReindexStatus, ReindexState } from './use_reindex_state'; @@ -37,16 +37,11 @@ export const ReindexStatusProvider: React.FunctionComponent = ({ indexName, children, }) => { - const { reindexState, startReindex, cancelReindex, updateStatus } = useReindexStatus({ + const { reindexState, startReindex, cancelReindex } = useReindexStatus({ indexName, api, }); - useEffect(() => { - updateStatus(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - return ( { errorMessage: null, reindexWarnings: [], hasRequiredPrivileges: true, + meta: { + indexName: 'myIndex', + reindexName: 'reindexed-myIndex', + aliases: [], + }, } as ReindexState, }; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx index ab2ec0d633323..809f47b4a295f 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/container.tsx @@ -64,6 +64,7 @@ export const ReindexFlyout: React.FunctionComponent = ({ const flyoutContents = showWarningsStep ? ( setShowWarningsStep(false)} continueReindex={() => { setShowWarningsStep(false); diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx index 1ee4cf2453bdc..5bf9a394f9738 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.test.tsx @@ -9,6 +9,7 @@ import { shallow } from 'enzyme'; import React from 'react'; import { ReindexStatus, ReindexStep } from '../../../../../../../common/types'; +import { LoadingState } from '../../../../types'; import type { ReindexState } from '../use_reindex_state'; import { ReindexProgress } from './progress'; @@ -22,6 +23,12 @@ describe('ReindexProgress', () => { status: ReindexStatus.inProgress, reindexTaskPercComplete: null, errorMessage: null, + loadingState: LoadingState.Success, + meta: { + indexName: 'foo', + reindexName: 'reindexed-foo', + aliases: [], + }, } as ReindexState } cancelReindex={jest.fn()} @@ -52,17 +59,29 @@ describe('ReindexProgress', () => { Object { "status": "inProgress", "title": + foo + , + } + } />, }, Object { "status": "incomplete", "title": + reindexed-foo + , + } + } />, }, Object { @@ -73,6 +92,12 @@ describe('ReindexProgress', () => { Object { "errorMessage": null, "lastCompletedStep": 0, + "loadingState": 1, + "meta": Object { + "aliases": Array [], + "indexName": "foo", + "reindexName": "reindexed-foo", + }, "reindexTaskPercComplete": null, "status": 0, } @@ -82,9 +107,32 @@ describe('ReindexProgress', () => { Object { "status": "incomplete", "title": + foo + , + "reindexName": + reindexed-foo + , + } + } + />, + }, + Object { + "status": "incomplete", + "title": + foo + , + } + } />, }, ] @@ -103,6 +151,12 @@ describe('ReindexProgress', () => { status: ReindexStatus.failed, reindexTaskPercComplete: 1, errorMessage: `This is an error that happened on alias switch`, + loadingState: LoadingState.Success, + meta: { + indexName: 'foo', + reindexName: 'reindexed-foo', + aliases: [], + }, } as ReindexState } cancelReindex={jest.fn()} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx index a58f386216a80..ed5c603deefc1 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/progress.tsx @@ -7,7 +7,15 @@ import React, { ReactNode } from 'react'; -import { EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiLink, EuiText, EuiTitle } from '@elastic/eui'; +import { + EuiCallOut, + EuiFlexGroup, + EuiFlexItem, + EuiLink, + EuiText, + EuiTitle, + EuiCode, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import { ReindexStatus, ReindexStep } from '../../../../../../../common/types'; @@ -124,95 +132,168 @@ const ReindexingDocumentsStepTitle: React.FunctionComponent<{ }; const orderedSteps = Object.values(ReindexStep).sort() as number[]; -const getStepTitle = (step: ReindexStep, inProgress?: boolean): ReactNode => { + +const getStepTitle = ( + step: ReindexStep, + meta: ReindexState['meta'], + inProgress?: boolean +): ReactNode => { if (step === ReindexStep.readonly) { return inProgress ? ( {meta.indexName}, + }} /> ) : ( {meta.indexName}, + }} /> ); } + if (step === ReindexStep.newIndexCreated) { return inProgress ? ( {meta.reindexName}, + }} /> ) : ( {meta.reindexName}, + }} /> ); } + if (step === ReindexStep.aliasCreated) { return inProgress ? ( {meta.indexName}, + reindexName: {meta.reindexName}, + }} + /> + ) : ( + {meta.indexName}, + reindexName: {meta.reindexName}, + }} + /> + ); + } + + if (step === ReindexStep.originalIndexDeleted) { + return inProgress ? ( + {meta.indexName}, + }} + /> + ) : ( + {meta.indexName}, + }} + /> + ); + } + + if (step === ReindexStep.existingAliasesUpdated) { + return inProgress ? ( + {`[${meta.aliases.join(',')}]`}, + reindexName: {meta.reindexName}, + }} /> ) : ( {`[${meta.aliases.join(',')}]`}, + reindexName: {meta.reindexName}, + }} /> ); } }; +interface Props { + reindexState: ReindexState; + cancelReindex: () => void; +} + /** * Displays a list of steps in the reindex operation, the current status, a progress bar, * and any error messages that are encountered. */ -export const ReindexProgress: React.FunctionComponent<{ - reindexState: ReindexState; - cancelReindex: () => void; -}> = (props) => { +export const ReindexProgress: React.FunctionComponent = (props) => { const { errorMessage, lastCompletedStep = -1, status, reindexTaskPercComplete, + meta, } = props.reindexState; + const getProgressStep = (thisStep: ReindexStep): StepProgressStep => { const previousStep = orderedSteps[orderedSteps.indexOf(thisStep) - 1]; if (status === ReindexStatus.failed && lastCompletedStep === previousStep) { return { - title: getStepTitle(thisStep), + title: getStepTitle(thisStep, meta), status: 'failed', children: , }; } else if (status === ReindexStatus.paused && lastCompletedStep === previousStep) { return { - title: getStepTitle(thisStep), + title: getStepTitle(thisStep, meta), status: 'paused', children: , }; } else if (status === ReindexStatus.cancelled && lastCompletedStep === previousStep) { return { - title: getStepTitle(thisStep), + title: getStepTitle(thisStep, meta), status: 'cancelled', }; } else if (status === undefined || lastCompletedStep < previousStep) { return { - title: getStepTitle(thisStep), + title: getStepTitle(thisStep, meta), status: 'incomplete', }; } else if (lastCompletedStep === previousStep) { return { - title: getStepTitle(thisStep, true), + title: getStepTitle(thisStep, meta, true), status: 'inProgress', }; } else { return { - title: getStepTitle(thisStep), + title: getStepTitle(thisStep, meta), status: 'complete', }; } @@ -259,8 +340,15 @@ export const ReindexProgress: React.FunctionComponent<{ getProgressStep(ReindexStep.newIndexCreated), reindexingDocsStep, getProgressStep(ReindexStep.aliasCreated), + getProgressStep(ReindexStep.originalIndexDeleted), ]; + const hasExistingAliases = meta.aliases.length > 0; + + if (hasExistingAliases) { + steps.push(getProgressStep(ReindexStep.existingAliasesUpdated)); + } + return ( <> @@ -270,7 +358,11 @@ export const ReindexProgress: React.FunctionComponent<{ id="xpack.upgradeAssistant.checkupTab.reindexing.flyout.checklistStep.reindexingInProgressTitle" defaultMessage="Reindexing in progress… {percents}" values={{ - percents: getReindexProgressLabel(reindexTaskPercComplete, lastCompletedStep), + percents: getReindexProgressLabel( + reindexTaskPercComplete, + lastCompletedStep, + hasExistingAliases + ), }} /> ) : ( diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx index 4eac1ec739cfc..bc944f7773ac7 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step.test.tsx @@ -40,6 +40,11 @@ describe('WarningsFlyoutStep', () => { warnings: [] as ReindexWarning[], hideWarningsStep: jest.fn(), continueReindex: jest.fn(), + meta: { + indexName: 'foo', + reindexName: 'reindexed-foo', + aliases: [], + }, }; it('renders', () => { diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step_checkbox.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step_checkbox.tsx index abc7e513f785f..39b3a722055f8 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step_checkbox.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warning_step_checkbox.tsx @@ -33,7 +33,7 @@ const WarningCheckbox: React.FunctionComponent<{ warningId: string; label: React.ReactNode; description: React.ReactNode; - documentationUrl: string; + documentationUrl?: string; onChange: (event: React.ChangeEvent) => void; }> = ({ isChecked, warningId, label, onChange, description, documentationUrl }) => ( <> @@ -47,20 +47,22 @@ const WarningCheckbox: React.FunctionComponent<{ onChange={onChange} /> - - - - } - position="right" - type="help" - /> - - + {documentationUrl !== undefined && ( + + + + } + position="right" + type="help" + /> + + + )} @@ -158,3 +160,35 @@ export const DeprecatedSettingWarningCheckbox: React.FunctionComponent ); }; + +export const ReplaceIndexWithAliasWarningCheckbox: React.FunctionComponent< + WarningCheckboxProps +> = ({ isChecked, onChange, docLinks, id, meta }) => { + return ( + {meta?.indexName}, + reindexName: {meta?.reindexName}, + }} + /> + } + description={ + {meta?.indexName}, + reindexName: {meta?.reindexName}, + }} + /> + } + /> + ); +}; diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx index 09cc8f103709a..97760b98e61ed 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/flyout/warnings_step.tsx @@ -20,11 +20,16 @@ import { } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { ReindexWarning, ReindexWarningTypes } from '../../../../../../../common/types'; +import { + ReindexWarning, + ReindexWarningTypes, + ReindexStatusResponse, +} from '../../../../../../../common/types'; import { useAppContext } from '../../../../../app_context'; import { CustomTypeNameWarningCheckbox, DeprecatedSettingWarningCheckbox, + ReplaceIndexWithAliasWarningCheckbox, WarningCheckboxProps, } from './warning_step_checkbox'; @@ -37,6 +42,7 @@ const warningToComponentMap: { } = { customTypeName: CustomTypeNameWarningCheckbox, indexSetting: DeprecatedSettingWarningCheckbox, + replaceIndexWithAlias: ReplaceIndexWithAliasWarningCheckbox, }; export const idForWarning = (id: number) => `reindexWarning-${id}`; @@ -44,6 +50,7 @@ interface WarningsConfirmationFlyoutProps { hideWarningsStep: () => void; continueReindex: () => void; warnings: ReindexWarning[]; + meta: ReindexStatusResponse['meta']; } /** @@ -54,6 +61,7 @@ export const WarningsFlyoutStep: React.FunctionComponent { const { services: { @@ -124,7 +132,7 @@ export const WarningsFlyoutStep: React.FunctionComponent ); })} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx index b181e666c17e2..68a754875a737 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/resolution_table_cell.tsx @@ -78,6 +78,7 @@ const i18nTexts = { export const ReindexResolutionCell: React.FunctionComponent = () => { const { reindexState } = useReindexContext(); + const hasExistingAliases = reindexState.meta.aliases.length > 0; if (reindexState.loadingState === LoadingState.Loading) { return ( @@ -104,7 +105,8 @@ export const ReindexResolutionCell: React.FunctionComponent = () => { {i18nTexts.reindexInProgressText}{' '} {getReindexProgressLabel( reindexState.reindexTaskPercComplete, - reindexState.lastCompletedStep + reindexState.lastCompletedStep, + hasExistingAliases )} diff --git a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx index e3a747e6615b8..9c1e5b932efdd 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx +++ b/x-pack/plugins/upgrade_assistant/public/application/components/es_deprecations/deprecation_types/reindex/use_reindex_state.tsx @@ -8,7 +8,7 @@ import { useRef, useCallback, useState, useEffect } from 'react'; import { - ReindexOperation, + ReindexStatusResponse, ReindexStatus, ReindexStep, ReindexWarning, @@ -27,20 +27,26 @@ export interface ReindexState { errorMessage: string | null; reindexWarnings?: ReindexWarning[]; hasRequiredPrivileges?: boolean; -} - -interface StatusResponse { - warnings?: ReindexWarning[]; - reindexOp?: ReindexOperation; - hasRequiredPrivileges?: boolean; + meta: { + indexName: string; + reindexName: string; + aliases: string[]; + }; } const getReindexState = ( reindexState: ReindexState, - { reindexOp, warnings, hasRequiredPrivileges }: StatusResponse + { reindexOp, warnings, hasRequiredPrivileges, meta: updatedMeta }: ReindexStatusResponse ) => { + const meta = { ...(updatedMeta ?? reindexState.meta) }; + // Once we have received an array of existing aliases, we won't update the meta value anymore because + // when we'll delete the original alias during the reindex process there won't be any aliases pointing + // to it anymore and the last reindex step (Update existing aliases) would be suddenly removed. + const aliases = + reindexState.meta.aliases.length > 0 ? reindexState.meta.aliases : updatedMeta.aliases; const newReindexState = { ...reindexState, + meta: { ...meta, aliases }, loadingState: LoadingState.Success, }; @@ -54,7 +60,23 @@ const getReindexState = ( if (reindexOp) { // Prevent the UI flickering back to inProgress after cancelling - newReindexState.lastCompletedStep = reindexOp.lastCompletedStep; + + let updateLastCompletedStep = true; + if ( + reindexOp.lastCompletedStep === ReindexStep.aliasCreated && + reindexOp.status !== ReindexStatus.completed + ) { + // "ReindexStep.aliasCreated" is the last step coming from the server + // There is a delay between the moment the server returns that the "lastCompletedStep" + // is "aliasCreated" and when the server marks reindexing as "completed". + // We will correct this timing error by only marking the "aliasCreated" step as done + // when the reindex status is "completed". + updateLastCompletedStep = false; + } + + if (updateLastCompletedStep) { + newReindexState.lastCompletedStep = reindexOp.lastCompletedStep; + } newReindexState.status = reindexOp.status; newReindexState.reindexTaskPercComplete = reindexOp.reindexTaskPercComplete; newReindexState.errorMessage = reindexOp.errorMessage; @@ -74,6 +96,11 @@ const getReindexState = ( reindexOp.status === ReindexStatus.inProgress ) { newReindexState.cancelLoadingState = CancelLoadingState.Loading; + } else if (newReindexState.status === ReindexStatus.completed) { + // The Elasticsearch reindex is complete. We will add one or two (depending if there are + // existing aliases that need to be updated) "fake" steps only for the UI. + // This will help our users understand what actually happened in the last step. + newReindexState.status = ReindexStatus.inProgress; } } @@ -85,6 +112,11 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A loadingState: LoadingState.Loading, errorMessage: null, reindexTaskPercComplete: null, + meta: { + indexName, + reindexName: '', // will be known after fetching the reindexStatus + aliases: [], // will be known after fetching the reindexStatus + }, }); const pollIntervalIdRef = useRef | null>(null); @@ -97,6 +129,52 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A } }, []); + /** + * When the server says that reindexing is complete we will fake + * one (or two in case there are existing aliases to update) extra steps in the UI + */ + const simulateExtraSteps = useCallback(() => { + const delay = 1000; + const hasExistingAliases = reindexState.meta.aliases.length > 0; + + // Mark "update existing aliases" as completed + const completeUpdateExistingAliasesStep = () => { + if (!isMounted.current) { + return; + } + + setReindexState((prevValue: ReindexState) => { + return { + ...prevValue, + status: ReindexStatus.completed, + lastCompletedStep: ReindexStep.existingAliasesUpdated, + }; + }); + }; + + // Mark "original index deleted" as completed + const completeDeleteOriginalIndexStep = () => { + if (!isMounted.current) { + return; + } + + setReindexState((prevValue: ReindexState) => { + return { + ...prevValue, + status: hasExistingAliases ? ReindexStatus.inProgress : ReindexStatus.completed, + lastCompletedStep: ReindexStep.originalIndexDeleted, + }; + }); + + if (hasExistingAliases) { + // Still one step to go! + setTimeout(completeUpdateExistingAliasesStep, delay); + } + }; + + setTimeout(completeDeleteOriginalIndexStep, delay); + }, [reindexState.meta.aliases.length]); + const updateStatus = useCallback(async () => { clearPollInterval(); @@ -114,15 +192,21 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A return; } + if (data === null) { + return; + } + setReindexState((prevValue: ReindexState) => { return getReindexState(prevValue, data); }); - // Only keep polling if it exists and is in progress. if (data.reindexOp && data.reindexOp.status === ReindexStatus.inProgress) { + // Only keep polling if it exists and is in progress. pollIntervalIdRef.current = setTimeout(updateStatus, POLL_INTERVAL); + } else if (data.reindexOp && data.reindexOp.status === ReindexStatus.completed) { + simulateExtraSteps(); } - }, [clearPollInterval, api, indexName]); + }, [clearPollInterval, api, indexName, simulateExtraSteps]); const startReindex = useCallback(async () => { setReindexState((prevValue: ReindexState) => { @@ -153,7 +237,7 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A } setReindexState((prevValue: ReindexState) => { - return getReindexState(prevValue, { reindexOp }); + return getReindexState(prevValue, { reindexOp, meta: prevValue.meta }); }); updateStatus(); }, [api, indexName, updateStatus]); @@ -179,6 +263,10 @@ export const useReindexStatus = ({ indexName, api }: { indexName: string; api: A } }, [api, indexName]); + useEffect(() => { + updateStatus(); + }, [updateStatus]); + useEffect(() => { isMounted.current = true; diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts index 5dcd49fa17958..f3c5680b56e20 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/api.ts @@ -13,6 +13,7 @@ import { ClusterUpgradeState, ResponseError, SystemIndicesMigrationStatus, + ReindexStatusResponse, } from '../../../common/types'; import { API_BASE_PATH, @@ -209,7 +210,7 @@ export class ApiService { } public async getReindexStatus(indexName: string) { - return await this.sendRequest({ + return await this.sendRequest({ path: `${API_BASE_PATH}/reindex/${indexName}`, method: 'get', }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/utils.test.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/utils.test.ts index 37392c832ecf5..b8eb245b631f6 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/utils.test.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/utils.test.ts @@ -54,15 +54,53 @@ describe('getReindexProgressLabel', () => { expect(getReindexProgressLabel(0, ReindexStep.reindexStarted)).toBe('10%'); }); - it('returns 53% when the reindexing documents progress is 0.5', () => { - expect(getReindexProgressLabel(0.5, ReindexStep.reindexStarted)).toBe('53%'); + it('returns 50% when the reindexing documents progress is 0.5', () => { + expect(getReindexProgressLabel(0.5, ReindexStep.reindexStarted)).toBe('50%'); }); - it('returns 95% when the reindexing documents progress is 1', () => { - expect(getReindexProgressLabel(1, ReindexStep.reindexStarted)).toBe('95%'); + it('returns 90% when the reindexing documents progress is 1', () => { + expect(getReindexProgressLabel(1, ReindexStep.reindexStarted)).toBe('90%'); }); - it('returns 100% when alias has been switched', () => { - expect(getReindexProgressLabel(null, ReindexStep.aliasCreated)).toBe('100%'); + it('returns 95% when alias has been created', () => { + expect(getReindexProgressLabel(null, ReindexStep.aliasCreated)).toBe('95%'); + }); + + it('returns 100% when original index has been deleted', () => { + expect(getReindexProgressLabel(null, ReindexStep.originalIndexDeleted)).toBe('100%'); + }); + + describe('when there are existing aliases', () => { + const withExistingAliases = true; + + it('returns 48% when the reindexing documents progress is 0.5', () => { + expect(getReindexProgressLabel(0.5, ReindexStep.reindexStarted, withExistingAliases)).toBe( + '48%' + ); + }); + + it('returns 85% when the reindexing documents progress is 1', () => { + expect(getReindexProgressLabel(1, ReindexStep.reindexStarted, withExistingAliases)).toBe( + '85%' + ); + }); + + it('returns 90% when alias has been created', () => { + expect(getReindexProgressLabel(null, ReindexStep.aliasCreated, withExistingAliases)).toBe( + '90%' + ); + }); + + it('returns 95% when original index has been deleted', () => { + expect( + getReindexProgressLabel(null, ReindexStep.originalIndexDeleted, withExistingAliases) + ).toBe('95%'); + }); + + it('returns 100% when original index has been deleted', () => { + expect( + getReindexProgressLabel(null, ReindexStep.existingAliasesUpdated, withExistingAliases) + ).toBe('100%'); + }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/public/application/lib/utils.ts b/x-pack/plugins/upgrade_assistant/public/application/lib/utils.ts index bdbc0949e368b..b13b20e7016f9 100644 --- a/x-pack/plugins/upgrade_assistant/public/application/lib/utils.ts +++ b/x-pack/plugins/upgrade_assistant/public/application/lib/utils.ts @@ -37,15 +37,17 @@ export const getDeprecationsUpperLimit = (count: number) => { }; /* - * Reindexing task consists of 4 steps: making the index read-only, creating a new index, - * reindexing documents into the new index and switching alias from the old to the new index. - * Steps 1, 2 and 4 each contribute 5% to the overall progress. + * Reindexing task consists of 5 (or 6) steps: making the index read-only, creating a new index, + * reindexing documents into the new index, creating an alias to point to the newly created index, + * delete the original index, (optionally) update existing aliases to point to the new index. + * Steps 1, 2 and 4, 5 & 6 each contribute 5% to the overall progress. * Step 3 (reindexing documents) can take a long time for large indices and its progress is calculated - * between 10% and 95% of the overall progress depending on its completeness percentage. + * between 10% and 90% of the overall progress depending on its completeness percentage. */ export const getReindexProgressLabel = ( reindexTaskPercComplete: number | null, - lastCompletedStep: ReindexStep | undefined + lastCompletedStep: ReindexStep | undefined, + hasExistingAliases: boolean = false ): string => { let percentsComplete = 0; switch (lastCompletedStep) { @@ -66,16 +68,28 @@ export const getReindexProgressLabel = ( case ReindexStep.reindexStarted: { // step 3 started, 10-95% progress depending on progress of reindexing documents in ES percentsComplete = - reindexTaskPercComplete !== null ? 10 + Math.round(reindexTaskPercComplete * 85) : 10; + reindexTaskPercComplete !== null + ? 10 + Math.round(reindexTaskPercComplete * (hasExistingAliases ? 75 : 80)) + : 10; break; } case ReindexStep.reindexCompleted: { - // step 3 completed, only step 4 remaining, 95% progress - percentsComplete = 95; + // step 3 completed + percentsComplete = hasExistingAliases ? 85 : 90; break; } case ReindexStep.aliasCreated: { - // step 4 completed, 100% progress + // step 4 completed + percentsComplete = hasExistingAliases ? 90 : 95; + break; + } + case ReindexStep.originalIndexDeleted: { + // step 5 completed + percentsComplete = hasExistingAliases ? 95 : 100; + break; + } + case ReindexStep.existingAliasesUpdated: { + // step 6 completed, 100% progress percentsComplete = 100; break; } diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index.ts index c1ff38b08678f..1ab6a26e90ffb 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index.ts @@ -7,3 +7,4 @@ export { reindexServiceFactory } from './reindex_service'; export { ReindexWorker } from './worker'; +export { generateNewIndexName } from './index_settings'; diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts index b68faf7f75b99..268846a31d2bd 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts @@ -164,13 +164,17 @@ describe('reindexService', () => { }); const reindexWarnings = await service.detectReindexWarnings(indexName); - expect(reindexWarnings).toEqual([]); + expect(reindexWarnings).toEqual([ + { + warningType: 'replaceIndexWithAlias', + }, + ]); }); it('returns null if index does not exist', async () => { actions.getFlatSettings.mockResolvedValueOnce(null); const reindexWarnings = await service.detectReindexWarnings('myIndex'); - expect(reindexWarnings).toBeNull(); + expect(reindexWarnings).toBeUndefined(); }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts index f9db1692ab1b7..db427161f50d3 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts @@ -42,7 +42,7 @@ export interface ReindexService { * Resolves to null if index does not exist. * @param indexName */ - detectReindexWarnings(indexName: string): Promise; + detectReindexWarnings(indexName: string): Promise; /** * Creates a new reindex operation for a given index. @@ -115,6 +115,8 @@ export interface ReindexService { * @param indexName */ cancelReindexing(indexName: string): Promise; + + getIndexAliases(indexName: string): any; } export const reindexServiceFactory = ( @@ -311,6 +313,14 @@ export const reindexServiceFactory = ( return reindexOp; }; + const getIndexAliases = async (indexName: string) => { + const { body: response } = await esClient.indices.getAlias({ + index: indexName, + }); + + return response[indexName]?.aliases ?? {}; + }; + /** * Creates an alias that points the old index to the new index, deletes the old index. * @param reindexOp @@ -318,11 +328,7 @@ export const reindexServiceFactory = ( const switchAlias = async (reindexOp: ReindexSavedObject) => { const { indexName, newIndexName, reindexOptions } = reindexOp.attributes; - const { body: response } = await esClient.indices.getAlias({ - index: indexName, - }); - - const existingAliases = response[indexName].aliases; + const existingAliases = await getIndexAliases(indexName); const extraAliases = Object.keys(existingAliases).map((aliasName) => ({ add: { index: newIndexName, alias: aliasName, ...existingAliases[aliasName] }, @@ -402,12 +408,21 @@ export const reindexServiceFactory = ( return resp.has_all_requested; }, - async detectReindexWarnings(indexName: string) { + async detectReindexWarnings(indexName: string): Promise { const flatSettings = await actions.getFlatSettings(indexName); + if (!flatSettings) { - return null; + return undefined; } else { - return getReindexWarnings(flatSettings); + return [ + // By default all reindexing operations will replace an index with an alias (with the same name) + // pointing to a newly created "reindexed" index. This is destructive as delete operations originally + // done on the index itself will now need to be done to the "reindexed-{indexName}" + { + warningType: 'replaceIndexWithAlias', + }, + ...getReindexWarnings(flatSettings), + ]; } }, @@ -602,5 +617,7 @@ export const reindexServiceFactory = ( return reindexOp; }, + + getIndexAliases, }; }; diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts index 9fcff5748a987..38a78f15f2b50 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.test.ts @@ -23,6 +23,7 @@ const mockReindexService = { processNextStep: jest.fn(), resumeReindexOperation: jest.fn(), cancelReindexing: jest.fn(), + getIndexAliases: jest.fn().mockResolvedValue({}), }; jest.mock('../../lib/es_version_precheck', () => ({ versionCheckHandlerWrapper: (a: any) => a, @@ -31,6 +32,7 @@ jest.mock('../../lib/es_version_precheck', () => ({ jest.mock('../../lib/reindexing', () => { return { reindexServiceFactory: () => mockReindexService, + generateNewIndexName: () => 'reindexed-foo', }; }); @@ -159,7 +161,7 @@ describe('reindex API', () => { expect(resp.status).toEqual(200); const data = resp.payload; - expect(data.reindexOp).toBeNull(); + expect(data.reindexOp).toBeUndefined(); expect(data.warnings).toBeNull(); }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts index 30f7c77cf73ab..d5776cb161b4d 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/reindex_indices/reindex_indices.ts @@ -9,8 +9,9 @@ import { schema } from '@kbn/config-schema'; import { errors } from '@elastic/elasticsearch'; import { API_BASE_PATH } from '../../../common/constants'; +import type { ReindexStatusResponse } from '../../../common/types'; import { versionCheckHandlerWrapper } from '../../lib/es_version_precheck'; -import { reindexServiceFactory, ReindexWorker } from '../../lib/reindexing'; +import { reindexServiceFactory, ReindexWorker, generateNewIndexName } from '../../lib/reindexing'; import { reindexActionsFactory } from '../../lib/reindexing/reindex_actions'; import { RouteDependencies } from '../../types'; import { mapAnyErrorToKibanaHttpResponse } from './map_any_error_to_kibana_http_response'; @@ -114,12 +115,21 @@ export function registerReindexIndicesRoutes( ? await reindexService.detectReindexWarnings(indexName) : []; - return response.ok({ - body: { - reindexOp: reindexOp ? reindexOp.attributes : null, - warnings, - hasRequiredPrivileges, + const indexAliases = await reindexService.getIndexAliases(indexName); + + const body: ReindexStatusResponse = { + reindexOp: reindexOp ? reindexOp.attributes : undefined, + warnings, + hasRequiredPrivileges, + meta: { + indexName, + reindexName: generateNewIndexName(indexName), + aliases: Object.keys(indexAliases), }, + }; + + return response.ok({ + body, }); } catch (error) { if (error instanceof errors.ResponseError) { diff --git a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js index d52f407e8483f..af2393d7b00d1 100644 --- a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js +++ b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js @@ -123,7 +123,10 @@ export default function ({ getService }) { it('shows no warnings', async () => { const resp = await supertest.get(`/api/upgrade_assistant/reindex/7.0-data`); - expect(resp.body.warnings.length).to.be(0); + // By default all reindexing operations will replace an index with an alias (with the same name) + // pointing to a newly created "reindexed" index. + expect(resp.body.warnings.length).to.be(1); + expect(resp.body.warnings[0].warningType).to.be('replaceIndexWithAlias'); }); it('reindexes old 7.0 index', async () => {