mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
# Backport This will backport the following commits from `main` to `8.6`: - [Do not skip UPDATE_TARGET_MAPPINGS if upgrading to a newer stack version (#147503)](https://github.com/elastic/kibana/pull/147503) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Gerard Soldevila","email":"gerard.soldevila@elastic.co"},"sourceCommit":{"committedDate":"2022-12-14T13:39:47Z","message":"Do not skip UPDATE_TARGET_MAPPINGS if upgrading to a newer stack version (#147503)\n\nFixes https://github.com/elastic/kibana/issues/147450","sha":"4f72a2eb5beded9a3086de7766021d9b65a197f3","branchLabelMapping":{"^v8.7.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","Team:Core","release_note:skip","Feature:Migrations","backport:prev-minor","v8.6.0","v8.7.0","v8.6.1"],"number":147503,"url":"https://github.com/elastic/kibana/pull/147503","mergeCommit":{"message":"Do not skip UPDATE_TARGET_MAPPINGS if upgrading to a newer stack version (#147503)\n\nFixes https://github.com/elastic/kibana/issues/147450","sha":"4f72a2eb5beded9a3086de7766021d9b65a197f3"}},"sourceBranch":"main","suggestedTargetBranches":["8.6"],"targetPullRequestStates":[{"branch":"8.6","label":"v8.6.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.7.0","labelRegex":"^v8.7.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/147503","number":147503,"mergeCommit":{"message":"Do not skip UPDATE_TARGET_MAPPINGS if upgrading to a newer stack version (#147503)\n\nFixes https://github.com/elastic/kibana/issues/147450","sha":"4f72a2eb5beded9a3086de7766021d9b65a197f3"}}]}] BACKPORT--> Co-authored-by: Gerard Soldevila <gerard.soldevila@elastic.co>
This commit is contained in:
parent
e4711bb3eb
commit
c9ca8486c0
7 changed files with 182 additions and 104 deletions
|
@ -15,13 +15,13 @@ jest.mock('../core/build_active_mappings');
|
|||
|
||||
const diffMappingsMock = diffMappings as jest.MockedFn<typeof diffMappings>;
|
||||
|
||||
const sourceIndexMappings: IndexMapping = {
|
||||
const actualMappings: IndexMapping = {
|
||||
properties: {
|
||||
field: { type: 'integer' },
|
||||
},
|
||||
};
|
||||
|
||||
const targetIndexMappings: IndexMapping = {
|
||||
const expectedMappings: IndexMapping = {
|
||||
properties: {
|
||||
field: { type: 'long' },
|
||||
},
|
||||
|
@ -34,7 +34,7 @@ describe('checkTargetMappings', () => {
|
|||
|
||||
it('returns match=false if source mappings are not defined', async () => {
|
||||
const task = checkTargetMappings({
|
||||
targetIndexMappings,
|
||||
expectedMappings,
|
||||
});
|
||||
|
||||
const result = await task();
|
||||
|
@ -44,21 +44,21 @@ describe('checkTargetMappings', () => {
|
|||
|
||||
it('calls diffMappings() with the source and target mappings', async () => {
|
||||
const task = checkTargetMappings({
|
||||
sourceIndexMappings,
|
||||
targetIndexMappings,
|
||||
actualMappings,
|
||||
expectedMappings,
|
||||
});
|
||||
|
||||
await task();
|
||||
expect(diffMappings).toHaveBeenCalledTimes(1);
|
||||
expect(diffMappings).toHaveBeenCalledWith(sourceIndexMappings, targetIndexMappings);
|
||||
expect(diffMappings).toHaveBeenCalledWith(actualMappings, expectedMappings);
|
||||
});
|
||||
|
||||
it('returns match=true if diffMappings() match', async () => {
|
||||
diffMappingsMock.mockReturnValueOnce(undefined);
|
||||
|
||||
const task = checkTargetMappings({
|
||||
sourceIndexMappings,
|
||||
targetIndexMappings,
|
||||
actualMappings,
|
||||
expectedMappings,
|
||||
});
|
||||
|
||||
const result = await task();
|
||||
|
@ -69,8 +69,8 @@ describe('checkTargetMappings', () => {
|
|||
diffMappingsMock.mockReturnValueOnce({ changedProp: 'field' });
|
||||
|
||||
const task = checkTargetMappings({
|
||||
sourceIndexMappings,
|
||||
targetIndexMappings,
|
||||
actualMappings,
|
||||
expectedMappings,
|
||||
});
|
||||
|
||||
const result = await task();
|
||||
|
|
|
@ -13,8 +13,8 @@ import { diffMappings } from '../core/build_active_mappings';
|
|||
|
||||
/** @internal */
|
||||
export interface CheckTargetMappingsParams {
|
||||
sourceIndexMappings?: IndexMapping;
|
||||
targetIndexMappings: IndexMapping;
|
||||
actualMappings?: IndexMapping;
|
||||
expectedMappings: IndexMapping;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
@ -24,13 +24,13 @@ export interface TargetMappingsCompareResult {
|
|||
|
||||
export const checkTargetMappings =
|
||||
({
|
||||
sourceIndexMappings,
|
||||
targetIndexMappings,
|
||||
actualMappings,
|
||||
expectedMappings,
|
||||
}: CheckTargetMappingsParams): TaskEither.TaskEither<never, TargetMappingsCompareResult> =>
|
||||
async () => {
|
||||
if (!sourceIndexMappings) {
|
||||
if (!actualMappings) {
|
||||
return Either.right({ match: false });
|
||||
}
|
||||
const diff = diffMappings(sourceIndexMappings, targetIndexMappings);
|
||||
const diff = diffMappings(actualMappings, expectedMappings);
|
||||
return Either.right({ match: !diff });
|
||||
};
|
||||
|
|
|
@ -115,6 +115,10 @@ export const model = (currentState: State, resW: ResponseType<AllActionStates>):
|
|||
sourceIndex: Option.none,
|
||||
targetIndex: `${stateP.indexPrefix}_${stateP.kibanaVersion}_001`,
|
||||
sourceIndexMappings: indices[source].mappings,
|
||||
// in this scenario, a .kibana_X.Y.Z_001 index exists that matches the current kibana version
|
||||
// aka we are NOT upgrading to a newer version
|
||||
// we inject the target index's current mappings in the state, to check them later
|
||||
targetIndexCurrentMappings: indices[source].mappings,
|
||||
targetIndexMappings: mergeMigrationMappingPropertyHashes(
|
||||
stateP.targetIndexMappings,
|
||||
indices[aliases[stateP.currentAlias]!].mappings
|
||||
|
|
|
@ -132,8 +132,8 @@ export const nextActionMap = (client: ElasticsearchClient, transformRawDocs: Tra
|
|||
Actions.refreshIndex({ client, targetIndex: state.targetIndex }),
|
||||
CHECK_TARGET_MAPPINGS: (state: CheckTargetMappingsState) =>
|
||||
Actions.checkTargetMappings({
|
||||
sourceIndexMappings: state.sourceIndexMappings,
|
||||
targetIndexMappings: state.targetIndexMappings,
|
||||
actualMappings: state.targetIndexCurrentMappings,
|
||||
expectedMappings: state.targetIndexMappings,
|
||||
}),
|
||||
UPDATE_TARGET_MAPPINGS: (state: UpdateTargetMappingsState) =>
|
||||
Actions.updateAndPickupMappings({
|
||||
|
|
|
@ -173,6 +173,7 @@ export interface PostInitState extends BaseState {
|
|||
readonly sourceIndex: Option.Option<string>;
|
||||
/** The target index is the index to which the migration writes */
|
||||
readonly targetIndex: string;
|
||||
readonly targetIndexCurrentMappings?: IndexMapping;
|
||||
readonly versionIndexReadyActions: Option.Option<AliasAction[]>;
|
||||
readonly outdatedDocumentsQuery: QueryDslQueryContainer;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
import Path from 'path';
|
||||
import fs from 'fs/promises';
|
||||
import { SemVer } from 'semver';
|
||||
import JSON5 from 'json5';
|
||||
import { Env } from '@kbn/config';
|
||||
import { REPO_ROOT } from '@kbn/utils';
|
||||
|
@ -77,88 +78,141 @@ describe('migration v2 - CHECK_TARGET_MAPPINGS', () => {
|
|||
expect(logIncludes(logs, 'CHECK_TARGET_MAPPINGS')).toEqual(false);
|
||||
});
|
||||
|
||||
it('skips UPDATE_TARGET_MAPPINGS for up-to-date deployments, when there are no changes in the mappings', async () => {
|
||||
const { startES } = createTestServers({
|
||||
adjustTimeout: (t: number) => jest.setTimeout(t),
|
||||
settings: {
|
||||
es: {
|
||||
license: 'basic',
|
||||
describe('when the indices are aligned with the stack version', () => {
|
||||
it('skips UPDATE_TARGET_MAPPINGS if there are no changes in the mappings', async () => {
|
||||
const { startES } = createTestServers({
|
||||
adjustTimeout: (t: number) => jest.setTimeout(t),
|
||||
settings: {
|
||||
es: {
|
||||
license: 'basic',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
esServer = await startES();
|
||||
|
||||
// start Kibana a first time to create the system indices
|
||||
root = createRoot();
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
|
||||
// stop Kibana and remove logs
|
||||
await root.shutdown();
|
||||
await delay(10);
|
||||
await removeLogFile();
|
||||
|
||||
root = createRoot();
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
|
||||
// Check for migration steps present in the logs
|
||||
logs = await parseLogFile();
|
||||
expect(logIncludes(logs, 'CREATE_NEW_TARGET')).toEqual(false);
|
||||
expect(
|
||||
logIncludes(logs, 'CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS')
|
||||
).toEqual(true);
|
||||
expect(logIncludes(logs, 'UPDATE_TARGET_MAPPINGS')).toEqual(false);
|
||||
expect(logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK')).toEqual(false);
|
||||
expect(logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_META')).toEqual(false);
|
||||
});
|
||||
|
||||
esServer = await startES();
|
||||
|
||||
// start Kibana a first time to create the system indices
|
||||
root = createRoot();
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
|
||||
// stop Kibana and remove logs
|
||||
await root.shutdown();
|
||||
await delay(10);
|
||||
await removeLogFile();
|
||||
|
||||
root = createRoot();
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
|
||||
// Check for migration steps present in the logs
|
||||
logs = await parseLogFile();
|
||||
expect(logIncludes(logs, 'CREATE_NEW_TARGET')).toEqual(false);
|
||||
expect(logIncludes(logs, 'CHECK_TARGET_MAPPINGS -> CHECK_VERSION_INDEX_READY_ACTIONS')).toEqual(
|
||||
true
|
||||
);
|
||||
expect(logIncludes(logs, 'UPDATE_TARGET_MAPPINGS')).toEqual(false);
|
||||
expect(logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK')).toEqual(false);
|
||||
expect(logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_META')).toEqual(false);
|
||||
});
|
||||
|
||||
it('runs UPDATE_TARGET_MAPPINGS when mappings have changed', async () => {
|
||||
describe('when upgrading to a newer stack version', () => {
|
||||
const currentVersion = Env.createDefault(REPO_ROOT, getEnvOptions()).packageInfo.version;
|
||||
|
||||
const { startES } = createTestServers({
|
||||
adjustTimeout: (t: number) => jest.setTimeout(t),
|
||||
settings: {
|
||||
es: {
|
||||
license: 'basic',
|
||||
dataArchive: Path.join(__dirname, 'archives', '8.4.0_with_sample_data_logs.zip'),
|
||||
it('runs UPDATE_TARGET_MAPPINGS when mappings have changed', async () => {
|
||||
const { startES } = createTestServers({
|
||||
adjustTimeout: (t: number) => jest.setTimeout(t),
|
||||
settings: {
|
||||
es: {
|
||||
license: 'basic',
|
||||
dataArchive: Path.join(__dirname, 'archives', '8.4.0_with_sample_data_logs.zip'),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
esServer = await startES();
|
||||
|
||||
// start Kibana a first time to create the system indices
|
||||
root = createRoot(currentVersion); // we discard a bunch of SO that have become unknown since 8.4.0
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
|
||||
// Check for migration steps present in the logs
|
||||
logs = await parseLogFile();
|
||||
expect(logIncludes(logs, 'CREATE_NEW_TARGET')).toEqual(false);
|
||||
expect(logIncludes(logs, 'CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS')).toEqual(true);
|
||||
expect(
|
||||
logIncludes(logs, 'UPDATE_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK')
|
||||
).toEqual(true);
|
||||
expect(
|
||||
logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK -> UPDATE_TARGET_MAPPINGS_META')
|
||||
).toEqual(true);
|
||||
expect(
|
||||
logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS')
|
||||
).toEqual(true);
|
||||
expect(
|
||||
logIncludes(logs, 'CHECK_VERSION_INDEX_READY_ACTIONS -> MARK_VERSION_INDEX_READY')
|
||||
).toEqual(true);
|
||||
expect(logIncludes(logs, 'MARK_VERSION_INDEX_READY -> DONE')).toEqual(true);
|
||||
expect(logIncludes(logs, 'Migration completed')).toEqual(true);
|
||||
});
|
||||
|
||||
esServer = await startES();
|
||||
it('runs UPDATE_TARGET_MAPPINGS even if the mappings have NOT changed', async () => {
|
||||
const { startES } = createTestServers({
|
||||
adjustTimeout: (t: number) => jest.setTimeout(t),
|
||||
settings: {
|
||||
es: {
|
||||
license: 'basic',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// start Kibana a first time to create the system indices
|
||||
root = createRoot(currentVersion); // we discard a bunch of SO that have become unknown since 8.4.0
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
esServer = await startES();
|
||||
|
||||
// Check for migration steps present in the logs
|
||||
logs = await parseLogFile();
|
||||
expect(logIncludes(logs, 'CREATE_NEW_TARGET')).toEqual(false);
|
||||
expect(logIncludes(logs, 'CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS')).toEqual(true);
|
||||
expect(
|
||||
logIncludes(logs, 'UPDATE_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK')
|
||||
).toEqual(true);
|
||||
expect(
|
||||
logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK -> UPDATE_TARGET_MAPPINGS_META')
|
||||
).toEqual(true);
|
||||
expect(
|
||||
logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS')
|
||||
).toEqual(true);
|
||||
expect(
|
||||
logIncludes(logs, 'CHECK_VERSION_INDEX_READY_ACTIONS -> MARK_VERSION_INDEX_READY')
|
||||
).toEqual(true);
|
||||
expect(logIncludes(logs, 'MARK_VERSION_INDEX_READY -> DONE')).toEqual(true);
|
||||
expect(logIncludes(logs, 'Migration completed')).toEqual(true);
|
||||
// start Kibana a first time to create the system indices
|
||||
root = createRoot();
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
|
||||
// stop Kibana and remove logs
|
||||
await root.shutdown();
|
||||
await delay(10);
|
||||
await removeLogFile();
|
||||
|
||||
const nextMinor = new SemVer(currentVersion).inc('patch').format();
|
||||
root = createRoot(undefined, nextMinor);
|
||||
await root.preboot();
|
||||
await root.setup();
|
||||
await root.start();
|
||||
|
||||
// Check for migration steps present in the logs
|
||||
logs = await parseLogFile();
|
||||
expect(logIncludes(logs, 'CREATE_NEW_TARGET')).toEqual(false);
|
||||
expect(logIncludes(logs, 'CHECK_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS')).toEqual(true);
|
||||
expect(
|
||||
logIncludes(logs, 'UPDATE_TARGET_MAPPINGS -> UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK')
|
||||
).toEqual(true);
|
||||
expect(
|
||||
logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_WAIT_FOR_TASK -> UPDATE_TARGET_MAPPINGS_META')
|
||||
).toEqual(true);
|
||||
expect(
|
||||
logIncludes(logs, 'UPDATE_TARGET_MAPPINGS_META -> CHECK_VERSION_INDEX_READY_ACTIONS')
|
||||
).toEqual(true);
|
||||
expect(
|
||||
logIncludes(logs, 'CHECK_VERSION_INDEX_READY_ACTIONS -> MARK_VERSION_INDEX_READY')
|
||||
).toEqual(true);
|
||||
expect(logIncludes(logs, 'MARK_VERSION_INDEX_READY -> DONE')).toEqual(true);
|
||||
expect(logIncludes(logs, 'Migration completed')).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createRoot(discardUnknownObjects?: string) {
|
||||
function createRoot(discardUnknownObjects?: string, customKibanaVersion?: string) {
|
||||
return createRootWithCorePlugins(
|
||||
{
|
||||
migrations: {
|
||||
|
@ -185,6 +239,7 @@ function createRoot(discardUnknownObjects?: string) {
|
|||
},
|
||||
{
|
||||
oss: true,
|
||||
}
|
||||
},
|
||||
customKibanaVersion
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { join } from 'path';
|
||||
import loadJsonFile from 'load-json-file';
|
||||
import { defaultsDeep } from 'lodash';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import supertest from 'supertest';
|
||||
|
@ -19,7 +21,7 @@ import {
|
|||
kibanaServerTestUser,
|
||||
systemIndicesSuperuser,
|
||||
} from '@kbn/test';
|
||||
import { CliArgs, Env } from '@kbn/config';
|
||||
import { CliArgs, Env, RawPackageInfo } from '@kbn/config';
|
||||
|
||||
import type { InternalCoreSetup, InternalCoreStart } from '@kbn/core-lifecycle-server-internal';
|
||||
import { Root } from '@kbn/core-root-server-internal';
|
||||
|
@ -45,22 +47,33 @@ const DEFAULTS_SETTINGS = {
|
|||
|
||||
export function createRootWithSettings(
|
||||
settings: Record<string, any>,
|
||||
cliArgs: Partial<CliArgs> = {}
|
||||
cliArgs: Partial<CliArgs> = {},
|
||||
customKibanaVersion?: string
|
||||
) {
|
||||
const env = Env.createDefault(REPO_ROOT, {
|
||||
configs: [],
|
||||
cliArgs: {
|
||||
dev: false,
|
||||
watch: false,
|
||||
basePath: false,
|
||||
runExamples: false,
|
||||
oss: true,
|
||||
disableOptimizer: true,
|
||||
cache: true,
|
||||
dist: false,
|
||||
...cliArgs,
|
||||
let pkg: RawPackageInfo | undefined;
|
||||
if (customKibanaVersion) {
|
||||
pkg = loadJsonFile.sync(join(REPO_ROOT, 'package.json')) as RawPackageInfo;
|
||||
pkg.version = customKibanaVersion;
|
||||
}
|
||||
|
||||
const env = Env.createDefault(
|
||||
REPO_ROOT,
|
||||
{
|
||||
configs: [],
|
||||
cliArgs: {
|
||||
dev: false,
|
||||
watch: false,
|
||||
basePath: false,
|
||||
runExamples: false,
|
||||
oss: true,
|
||||
disableOptimizer: true,
|
||||
cache: true,
|
||||
dist: false,
|
||||
...cliArgs,
|
||||
},
|
||||
},
|
||||
});
|
||||
pkg
|
||||
);
|
||||
|
||||
return new Root(
|
||||
{
|
||||
|
@ -103,7 +116,11 @@ export function createRoot(settings = {}, cliArgs: Partial<CliArgs> = {}) {
|
|||
* @param {Object} [settings={}] Any config overrides for this instance.
|
||||
* @returns {Root}
|
||||
*/
|
||||
export function createRootWithCorePlugins(settings = {}, cliArgs: Partial<CliArgs> = {}) {
|
||||
export function createRootWithCorePlugins(
|
||||
settings = {},
|
||||
cliArgs: Partial<CliArgs> = {},
|
||||
customKibanaVersion?: string
|
||||
) {
|
||||
const DEFAULT_SETTINGS_WITH_CORE_PLUGINS = {
|
||||
elasticsearch: {
|
||||
hosts: [esTestConfig.getUrl()],
|
||||
|
@ -144,7 +161,8 @@ export function createRootWithCorePlugins(settings = {}, cliArgs: Partial<CliArg
|
|||
|
||||
return createRootWithSettings(
|
||||
defaultsDeep({}, settings, DEFAULT_SETTINGS_WITH_CORE_PLUGINS),
|
||||
cliArgs
|
||||
cliArgs,
|
||||
customKibanaVersion
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue