mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[saved objects] Remove migrations enableV2
config. (#115655)
This commit is contained in:
parent
a7a1e5436b
commit
a7fff86390
34 changed files with 129 additions and 369 deletions
|
@ -395,9 +395,6 @@ override this parameter to use their own Tile Map Service. For example:
|
|||
| `migrations.maxBatchSizeBytes:`
|
||||
| Defines the maximum payload size for indexing batches of upgraded saved objects to avoid migrations failing due to a 413 Request Entity Too Large response from Elasticsearch. This value should be lower than or equal to your Elasticsearch cluster's `http.max_content_length` configuration option. *Default: `100mb`*
|
||||
|
||||
| `migrations.enableV2:`
|
||||
| experimental[]. Enables the new Saved Objects migration algorithm. For information about the migration algorithm, refer to <<upgrade-migrations>>. When `migrations v2` is stable, the setting will be removed in an upcoming release without any further notice. Setting the value to `false` causes {kib} to use the legacy migration algorithm, which shipped in 7.11 and earlier versions. *Default: `true`*
|
||||
|
||||
| `migrations.retryAttempts:`
|
||||
| The number of times migrations retry temporary failures, such as a network timeout, 503 status code, or `snapshot_in_progress_exception`. When upgrade migrations frequently fail after exhausting all retry attempts with a message such as `Unable to complete the [...] step after 15 attempts, terminating.`, increase the setting value. *Default: `15`*
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ import { deleteUnknownTypeObjects, getUnknownTypesDeprecations } from './unknown
|
|||
import { typeRegistryMock } from '../saved_objects_type_registry.mock';
|
||||
import { elasticsearchClientMock } from '../../elasticsearch/client/mocks';
|
||||
import type { KibanaConfigType } from '../../kibana_config';
|
||||
import type { SavedObjectConfig } from '../saved_objects_config';
|
||||
import { SavedObjectsType } from 'kibana/server';
|
||||
|
||||
const createSearchResponse = (count: number): estypes.SearchResponse => {
|
||||
|
@ -32,7 +31,6 @@ describe('unknown saved object types deprecation', () => {
|
|||
let typeRegistry: ReturnType<typeof typeRegistryMock.create>;
|
||||
let esClient: ReturnType<typeof elasticsearchClientMock.createScopedClusterClient>;
|
||||
let kibanaConfig: KibanaConfigType;
|
||||
let savedObjectsConfig: SavedObjectConfig;
|
||||
|
||||
beforeEach(() => {
|
||||
typeRegistry = typeRegistryMock.create();
|
||||
|
@ -48,12 +46,6 @@ describe('unknown saved object types deprecation', () => {
|
|||
index: '.kibana',
|
||||
enabled: true,
|
||||
};
|
||||
|
||||
savedObjectsConfig = {
|
||||
migration: {
|
||||
enableV2: true,
|
||||
},
|
||||
} as SavedObjectConfig;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -69,7 +61,6 @@ describe('unknown saved object types deprecation', () => {
|
|||
|
||||
it('calls `esClient.asInternalUser.search` with the correct parameters', async () => {
|
||||
await getUnknownTypesDeprecations({
|
||||
savedObjectsConfig,
|
||||
esClient,
|
||||
typeRegistry,
|
||||
kibanaConfig,
|
||||
|
@ -96,7 +87,6 @@ describe('unknown saved object types deprecation', () => {
|
|||
);
|
||||
|
||||
const deprecations = await getUnknownTypesDeprecations({
|
||||
savedObjectsConfig,
|
||||
esClient,
|
||||
typeRegistry,
|
||||
kibanaConfig,
|
||||
|
@ -112,7 +102,6 @@ describe('unknown saved object types deprecation', () => {
|
|||
);
|
||||
|
||||
const deprecations = await getUnknownTypesDeprecations({
|
||||
savedObjectsConfig,
|
||||
esClient,
|
||||
typeRegistry,
|
||||
kibanaConfig,
|
||||
|
@ -141,7 +130,6 @@ describe('unknown saved object types deprecation', () => {
|
|||
describe('deleteUnknownTypeObjects', () => {
|
||||
it('calls `esClient.asInternalUser.search` with the correct parameters', async () => {
|
||||
await deleteUnknownTypeObjects({
|
||||
savedObjectsConfig,
|
||||
esClient,
|
||||
typeRegistry,
|
||||
kibanaConfig,
|
||||
|
|
|
@ -13,14 +13,12 @@ import { IScopedClusterClient } from '../../elasticsearch';
|
|||
import { ISavedObjectTypeRegistry } from '../saved_objects_type_registry';
|
||||
import { SavedObjectsRawDocSource } from '../serialization';
|
||||
import type { KibanaConfigType } from '../../kibana_config';
|
||||
import type { SavedObjectConfig } from '../saved_objects_config';
|
||||
import { getIndexForType } from '../service/lib';
|
||||
|
||||
interface UnknownTypesDeprecationOptions {
|
||||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
esClient: IScopedClusterClient;
|
||||
kibanaConfig: KibanaConfigType;
|
||||
savedObjectsConfig: SavedObjectConfig;
|
||||
kibanaVersion: string;
|
||||
}
|
||||
|
||||
|
@ -32,11 +30,9 @@ const getTargetIndices = ({
|
|||
typeRegistry,
|
||||
kibanaVersion,
|
||||
kibanaConfig,
|
||||
savedObjectsConfig,
|
||||
}: {
|
||||
types: string[];
|
||||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
savedObjectsConfig: SavedObjectConfig;
|
||||
kibanaConfig: KibanaConfigType;
|
||||
kibanaVersion: string;
|
||||
}) => {
|
||||
|
@ -46,7 +42,6 @@ const getTargetIndices = ({
|
|||
getIndexForType({
|
||||
type,
|
||||
typeRegistry,
|
||||
migV2Enabled: savedObjectsConfig.migration.enableV2,
|
||||
kibanaVersion,
|
||||
defaultIndex: kibanaConfig.index,
|
||||
})
|
||||
|
@ -69,7 +64,6 @@ const getUnknownSavedObjects = async ({
|
|||
typeRegistry,
|
||||
esClient,
|
||||
kibanaConfig,
|
||||
savedObjectsConfig,
|
||||
kibanaVersion,
|
||||
}: UnknownTypesDeprecationOptions) => {
|
||||
const knownTypes = getKnownTypes(typeRegistry);
|
||||
|
@ -78,7 +72,6 @@ const getUnknownSavedObjects = async ({
|
|||
typeRegistry,
|
||||
kibanaConfig,
|
||||
kibanaVersion,
|
||||
savedObjectsConfig,
|
||||
});
|
||||
const query = getUnknownTypesQuery(knownTypes);
|
||||
|
||||
|
@ -141,7 +134,6 @@ interface DeleteUnknownTypesOptions {
|
|||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
esClient: IScopedClusterClient;
|
||||
kibanaConfig: KibanaConfigType;
|
||||
savedObjectsConfig: SavedObjectConfig;
|
||||
kibanaVersion: string;
|
||||
}
|
||||
|
||||
|
@ -149,7 +141,6 @@ export const deleteUnknownTypeObjects = async ({
|
|||
esClient,
|
||||
typeRegistry,
|
||||
kibanaConfig,
|
||||
savedObjectsConfig,
|
||||
kibanaVersion,
|
||||
}: DeleteUnknownTypesOptions) => {
|
||||
const knownTypes = getKnownTypes(typeRegistry);
|
||||
|
@ -158,7 +149,6 @@ export const deleteUnknownTypeObjects = async ({
|
|||
typeRegistry,
|
||||
kibanaConfig,
|
||||
kibanaVersion,
|
||||
savedObjectsConfig,
|
||||
});
|
||||
const query = getUnknownTypesQuery(knownTypes);
|
||||
|
||||
|
|
|
@ -42,8 +42,6 @@ const createMigrator = (
|
|||
scrollDuration: '15m',
|
||||
pollInterval: 1500,
|
||||
skip: false,
|
||||
// TODO migrationsV2: remove/deprecate once we remove migrations v1
|
||||
enableV2: false,
|
||||
retryAttempts: 10,
|
||||
},
|
||||
runMigrations: jest.fn(),
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { take } from 'rxjs/operators';
|
||||
import { estypes, errors as esErrors } from '@elastic/elasticsearch';
|
||||
import { estypes } from '@elastic/elasticsearch';
|
||||
|
||||
import { elasticsearchClientMock } from '../../../elasticsearch/client/mocks';
|
||||
import { KibanaMigratorOptions, KibanaMigrator } from './kibana_migrator';
|
||||
|
@ -125,13 +125,6 @@ describe('KibanaMigrator', () => {
|
|||
it('only runs migrations once if called multiple times', async () => {
|
||||
const options = mockOptions();
|
||||
|
||||
options.client.cat.templates.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise(
|
||||
// @ts-expect-error
|
||||
{ templates: [] } as CatTemplatesResponse,
|
||||
{ statusCode: 404 }
|
||||
)
|
||||
);
|
||||
options.client.indices.get.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise({}, { statusCode: 404 })
|
||||
);
|
||||
|
@ -144,159 +137,79 @@ describe('KibanaMigrator', () => {
|
|||
migrator.prepareMigrations();
|
||||
await migrator.runMigrations();
|
||||
await migrator.runMigrations();
|
||||
await migrator.runMigrations();
|
||||
|
||||
expect(options.client.cat.templates).toHaveBeenCalledTimes(1);
|
||||
// indices.get is called twice during a single migration
|
||||
expect(options.client.indices.get).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
describe('when enableV2 = false', () => {
|
||||
it('when enableV2 = false creates an IndexMigrator which retries NoLivingConnectionsError errors from ES client', async () => {
|
||||
const options = mockOptions();
|
||||
it('emits results on getMigratorResult$()', async () => {
|
||||
const options = mockV2MigrationOptions();
|
||||
const migrator = new KibanaMigrator(options);
|
||||
const migratorStatus = migrator.getStatus$().pipe(take(3)).toPromise();
|
||||
migrator.prepareMigrations();
|
||||
await migrator.runMigrations();
|
||||
|
||||
options.client.cat.templates.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise(
|
||||
// @ts-expect-error
|
||||
{ templates: [] } as CatTemplatesResponse,
|
||||
{ statusCode: 404 }
|
||||
)
|
||||
);
|
||||
options.client.indices.get.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise({}, { statusCode: 404 })
|
||||
);
|
||||
options.client.indices.getAlias.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise({}, { statusCode: 404 })
|
||||
);
|
||||
|
||||
options.client.indices.create = jest
|
||||
.fn()
|
||||
.mockReturnValueOnce(
|
||||
elasticsearchClientMock.createErrorTransportRequestPromise(
|
||||
new esErrors.NoLivingConnectionsError('reason', {} as any)
|
||||
)
|
||||
)
|
||||
.mockImplementationOnce(() =>
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise('success')
|
||||
);
|
||||
|
||||
const migrator = new KibanaMigrator(options);
|
||||
const migratorStatus = migrator.getStatus$().pipe(take(3)).toPromise();
|
||||
|
||||
migrator.prepareMigrations();
|
||||
await migrator.runMigrations();
|
||||
|
||||
expect(options.client.indices.create).toHaveBeenCalledTimes(3);
|
||||
const { status } = await migratorStatus;
|
||||
return expect(status).toEqual('completed');
|
||||
const { status, result } = await migratorStatus;
|
||||
expect(status).toEqual('completed');
|
||||
expect(result![0]).toMatchObject({
|
||||
destIndex: '.my-index_8.2.3_001',
|
||||
sourceIndex: '.my-index_pre8.2.3_001',
|
||||
elapsedMs: expect.any(Number),
|
||||
status: 'migrated',
|
||||
});
|
||||
|
||||
it('emits results on getMigratorResult$()', async () => {
|
||||
const options = mockOptions();
|
||||
|
||||
options.client.cat.templates.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise(
|
||||
// @ts-expect-error
|
||||
{ templates: [] } as CatTemplatesResponse,
|
||||
{ statusCode: 404 }
|
||||
)
|
||||
);
|
||||
options.client.indices.get.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise({}, { statusCode: 404 })
|
||||
);
|
||||
options.client.indices.getAlias.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise({}, { statusCode: 404 })
|
||||
);
|
||||
|
||||
const migrator = new KibanaMigrator(options);
|
||||
const migratorStatus = migrator.getStatus$().pipe(take(3)).toPromise();
|
||||
migrator.prepareMigrations();
|
||||
await migrator.runMigrations();
|
||||
const { status, result } = await migratorStatus;
|
||||
expect(status).toEqual('completed');
|
||||
expect(result![0]).toMatchObject({
|
||||
destIndex: '.my-index_1',
|
||||
elapsedMs: expect.any(Number),
|
||||
sourceIndex: '.my-index',
|
||||
status: 'migrated',
|
||||
});
|
||||
expect(result![1]).toMatchObject({
|
||||
destIndex: 'other-index_1',
|
||||
elapsedMs: expect.any(Number),
|
||||
sourceIndex: 'other-index',
|
||||
status: 'migrated',
|
||||
});
|
||||
expect(result![1]).toMatchObject({
|
||||
destIndex: 'other-index_8.2.3_001',
|
||||
elapsedMs: expect.any(Number),
|
||||
status: 'patched',
|
||||
});
|
||||
});
|
||||
describe('when enableV2 = true', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('emits results on getMigratorResult$()', async () => {
|
||||
const options = mockV2MigrationOptions();
|
||||
const migrator = new KibanaMigrator(options);
|
||||
const migratorStatus = migrator.getStatus$().pipe(take(3)).toPromise();
|
||||
migrator.prepareMigrations();
|
||||
await migrator.runMigrations();
|
||||
|
||||
const { status, result } = await migratorStatus;
|
||||
expect(status).toEqual('completed');
|
||||
expect(result![0]).toMatchObject({
|
||||
destIndex: '.my-index_8.2.3_001',
|
||||
sourceIndex: '.my-index_pre8.2.3_001',
|
||||
elapsedMs: expect.any(Number),
|
||||
status: 'migrated',
|
||||
});
|
||||
expect(result![1]).toMatchObject({
|
||||
destIndex: 'other-index_8.2.3_001',
|
||||
elapsedMs: expect.any(Number),
|
||||
status: 'patched',
|
||||
});
|
||||
});
|
||||
it('rejects when the migration state machine terminates in a FATAL state', () => {
|
||||
const options = mockV2MigrationOptions();
|
||||
options.client.indices.get.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise(
|
||||
{
|
||||
'.my-index_8.2.4_001': {
|
||||
aliases: {
|
||||
'.my-index': {},
|
||||
'.my-index_8.2.4': {},
|
||||
},
|
||||
mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } },
|
||||
settings: {},
|
||||
it('rejects when the migration state machine terminates in a FATAL state', () => {
|
||||
const options = mockV2MigrationOptions();
|
||||
options.client.indices.get.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise(
|
||||
{
|
||||
'.my-index_8.2.4_001': {
|
||||
aliases: {
|
||||
'.my-index': {},
|
||||
'.my-index_8.2.4': {},
|
||||
},
|
||||
mappings: { properties: {}, _meta: { migrationMappingPropertyHashes: {} } },
|
||||
settings: {},
|
||||
},
|
||||
{ statusCode: 200 }
|
||||
)
|
||||
);
|
||||
},
|
||||
{ statusCode: 200 }
|
||||
)
|
||||
);
|
||||
|
||||
const migrator = new KibanaMigrator(options);
|
||||
migrator.prepareMigrations();
|
||||
return expect(migrator.runMigrations()).rejects.toMatchInlineSnapshot(
|
||||
`[Error: Unable to complete saved object migrations for the [.my-index] index: The .my-index alias is pointing to a newer version of Kibana: v8.2.4]`
|
||||
);
|
||||
});
|
||||
it('rejects when an unexpected exception occurs in an action', async () => {
|
||||
const options = mockV2MigrationOptions();
|
||||
options.client.tasks.get.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise({
|
||||
completed: true,
|
||||
error: { type: 'elasticsearch_exception', reason: 'task failed with an error' },
|
||||
failures: [],
|
||||
task: { description: 'task description' } as any,
|
||||
})
|
||||
);
|
||||
const migrator = new KibanaMigrator(options);
|
||||
migrator.prepareMigrations();
|
||||
return expect(migrator.runMigrations()).rejects.toMatchInlineSnapshot(
|
||||
`[Error: Unable to complete saved object migrations for the [.my-index] index: The .my-index alias is pointing to a newer version of Kibana: v8.2.4]`
|
||||
);
|
||||
});
|
||||
|
||||
const migrator = new KibanaMigrator(options);
|
||||
migrator.prepareMigrations();
|
||||
await expect(migrator.runMigrations()).rejects.toMatchInlineSnapshot(`
|
||||
[Error: Unable to complete saved object migrations for the [.my-index] index. Error: Reindex failed with the following error:
|
||||
{"_tag":"Some","value":{"type":"elasticsearch_exception","reason":"task failed with an error"}}]
|
||||
`);
|
||||
expect(loggingSystemMock.collect(options.logger).error[0][0]).toMatchInlineSnapshot(`
|
||||
[Error: Reindex failed with the following error:
|
||||
{"_tag":"Some","value":{"type":"elasticsearch_exception","reason":"task failed with an error"}}]
|
||||
`);
|
||||
});
|
||||
it('rejects when an unexpected exception occurs in an action', async () => {
|
||||
const options = mockV2MigrationOptions();
|
||||
options.client.tasks.get.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise({
|
||||
completed: true,
|
||||
error: { type: 'elasticsearch_exception', reason: 'task failed with an error' },
|
||||
failures: [],
|
||||
task: { description: 'task description' } as any,
|
||||
})
|
||||
);
|
||||
|
||||
const migrator = new KibanaMigrator(options);
|
||||
migrator.prepareMigrations();
|
||||
await expect(migrator.runMigrations()).rejects.toMatchInlineSnapshot(`
|
||||
[Error: Unable to complete saved object migrations for the [.my-index] index. Error: Reindex failed with the following error:
|
||||
{"_tag":"Some","value":{"type":"elasticsearch_exception","reason":"task failed with an error"}}]
|
||||
`);
|
||||
expect(loggingSystemMock.collect(options.logger).error[0][0]).toMatchInlineSnapshot(`
|
||||
[Error: Reindex failed with the following error:
|
||||
{"_tag":"Some","value":{"type":"elasticsearch_exception","reason":"task failed with an error"}}]
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -306,7 +219,7 @@ type MockedOptions = KibanaMigratorOptions & {
|
|||
};
|
||||
|
||||
const mockV2MigrationOptions = () => {
|
||||
const options = mockOptions({ enableV2: true });
|
||||
const options = mockOptions();
|
||||
|
||||
options.client.indices.get.mockReturnValue(
|
||||
elasticsearchClientMock.createSuccessTransportRequestPromise(
|
||||
|
@ -362,7 +275,7 @@ const mockV2MigrationOptions = () => {
|
|||
return options;
|
||||
};
|
||||
|
||||
const mockOptions = ({ enableV2 }: { enableV2: boolean } = { enableV2: false }) => {
|
||||
const mockOptions = () => {
|
||||
const options: MockedOptions = {
|
||||
logger: loggingSystemMock.create().get(),
|
||||
kibanaVersion: '8.2.3',
|
||||
|
@ -401,7 +314,6 @@ const mockOptions = ({ enableV2 }: { enableV2: boolean } = { enableV2: false })
|
|||
pollInterval: 20000,
|
||||
scrollDuration: '10m',
|
||||
skip: false,
|
||||
enableV2,
|
||||
retryAttempts: 20,
|
||||
},
|
||||
client: elasticsearchClientMock.createElasticsearchClient(),
|
||||
|
|
|
@ -22,13 +22,7 @@ import {
|
|||
SavedObjectsSerializer,
|
||||
SavedObjectsRawDoc,
|
||||
} from '../../serialization';
|
||||
import {
|
||||
buildActiveMappings,
|
||||
createMigrationEsClient,
|
||||
IndexMigrator,
|
||||
MigrationResult,
|
||||
MigrationStatus,
|
||||
} from '../core';
|
||||
import { buildActiveMappings, MigrationResult, MigrationStatus } from '../core';
|
||||
import { DocumentMigrator, VersionedTransformer } from '../core/document_migrator';
|
||||
import { createIndexMap } from '../core/build_index_map';
|
||||
import { SavedObjectsMigrationConfigType } from '../../saved_objects_config';
|
||||
|
@ -71,7 +65,6 @@ export class KibanaMigrator {
|
|||
status: 'waiting_to_start',
|
||||
});
|
||||
private readonly activeMappings: IndexMapping;
|
||||
private migrationsRetryDelay?: number;
|
||||
// TODO migrationsV2: make private once we remove migrations v1
|
||||
public readonly kibanaVersion: string;
|
||||
// TODO migrationsV2: make private once we remove migrations v1
|
||||
|
@ -105,7 +98,6 @@ export class KibanaMigrator {
|
|||
// Building the active mappings (and associated md5sums) is an expensive
|
||||
// operation so we cache the result
|
||||
this.activeMappings = buildActiveMappings(this.mappingProperties);
|
||||
this.migrationsRetryDelay = migrationsRetryDelay;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -173,49 +165,28 @@ export class KibanaMigrator {
|
|||
});
|
||||
|
||||
const migrators = Object.keys(indexMap).map((index) => {
|
||||
// TODO migrationsV2: remove old migrations algorithm
|
||||
if (this.soMigrationsConfig.enableV2) {
|
||||
return {
|
||||
migrate: (): Promise<MigrationResult> => {
|
||||
return runResilientMigrator({
|
||||
client: this.client,
|
||||
kibanaVersion: this.kibanaVersion,
|
||||
targetMappings: buildActiveMappings(indexMap[index].typeMappings),
|
||||
logger: this.log,
|
||||
preMigrationScript: indexMap[index].script,
|
||||
transformRawDocs: (rawDocs: SavedObjectsRawDoc[]) =>
|
||||
migrateRawDocsSafely({
|
||||
serializer: this.serializer,
|
||||
knownTypes: new Set(this.typeRegistry.getAllTypes().map((t) => t.name)),
|
||||
migrateDoc: this.documentMigrator.migrateAndConvert,
|
||||
rawDocs,
|
||||
}),
|
||||
migrationVersionPerType: this.documentMigrator.migrationVersion,
|
||||
indexPrefix: index,
|
||||
migrationsConfig: this.soMigrationsConfig,
|
||||
typeRegistry: this.typeRegistry,
|
||||
});
|
||||
},
|
||||
};
|
||||
} else {
|
||||
return new IndexMigrator({
|
||||
batchSize: this.soMigrationsConfig.batchSize,
|
||||
client: createMigrationEsClient(this.client, this.log, this.migrationsRetryDelay),
|
||||
documentMigrator: this.documentMigrator,
|
||||
index,
|
||||
kibanaVersion: this.kibanaVersion,
|
||||
log: this.log,
|
||||
mappingProperties: indexMap[index].typeMappings,
|
||||
setStatus: (status) => this.status$.next(status),
|
||||
pollInterval: this.soMigrationsConfig.pollInterval,
|
||||
scrollDuration: this.soMigrationsConfig.scrollDuration,
|
||||
serializer: this.serializer,
|
||||
// Only necessary for the migrator of the kibana index.
|
||||
obsoleteIndexTemplatePattern:
|
||||
index === kibanaIndexName ? 'kibana_index_template*' : undefined,
|
||||
convertToAliasScript: indexMap[index].script,
|
||||
});
|
||||
}
|
||||
return {
|
||||
migrate: (): Promise<MigrationResult> => {
|
||||
return runResilientMigrator({
|
||||
client: this.client,
|
||||
kibanaVersion: this.kibanaVersion,
|
||||
targetMappings: buildActiveMappings(indexMap[index].typeMappings),
|
||||
logger: this.log,
|
||||
preMigrationScript: indexMap[index].script,
|
||||
transformRawDocs: (rawDocs: SavedObjectsRawDoc[]) =>
|
||||
migrateRawDocsSafely({
|
||||
serializer: this.serializer,
|
||||
knownTypes: new Set(this.typeRegistry.getAllTypes().map((t) => t.name)),
|
||||
migrateDoc: this.documentMigrator.migrateAndConvert,
|
||||
rawDocs,
|
||||
}),
|
||||
migrationVersionPerType: this.documentMigrator.migrationVersion,
|
||||
indexPrefix: index,
|
||||
migrationsConfig: this.soMigrationsConfig,
|
||||
typeRegistry: this.typeRegistry,
|
||||
});
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return Promise.all(migrators.map((migrator) => migrator.migrate()));
|
||||
|
|
|
@ -49,7 +49,6 @@ describe('migration from 7.7.2-xpack with 100k objects', () => {
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
},
|
||||
logging: {
|
||||
appenders: {
|
||||
|
|
|
@ -113,7 +113,6 @@ function createRoot() {
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
batchSize: 250,
|
||||
},
|
||||
logging: {
|
||||
|
|
|
@ -155,7 +155,6 @@ function createRoot() {
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
batchSize: 5,
|
||||
},
|
||||
logging: {
|
||||
|
|
|
@ -217,7 +217,6 @@ function createRoot() {
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
batchSize: 5,
|
||||
},
|
||||
logging: {
|
||||
|
|
|
@ -137,7 +137,6 @@ function createRoot(options: { maxBatchSizeBytes?: number }) {
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
batchSize: 1000,
|
||||
maxBatchSizeBytes: options.maxBatchSizeBytes,
|
||||
},
|
||||
|
|
|
@ -88,7 +88,6 @@ function createRoot(options: { maxBatchSizeBytes?: number }) {
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
batchSize: 1000,
|
||||
maxBatchSizeBytes: options.maxBatchSizeBytes,
|
||||
},
|
||||
|
|
|
@ -28,7 +28,6 @@ function createRoot() {
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
},
|
||||
logging: {
|
||||
appenders: {
|
||||
|
|
|
@ -149,7 +149,6 @@ function createRoot() {
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
batchSize: 5,
|
||||
},
|
||||
logging: {
|
||||
|
|
|
@ -153,7 +153,6 @@ function createRoot() {
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
batchSize: 5,
|
||||
},
|
||||
logging: {
|
||||
|
|
|
@ -77,7 +77,6 @@ describe('migrating from 7.3.0-xpack which used v1 migrations', () => {
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
// There are 40 docs in fixtures. Batch size configured to enforce 3 migration steps.
|
||||
batchSize: 15,
|
||||
},
|
||||
|
|
|
@ -77,7 +77,6 @@ describe('migrating from the same Kibana version that used v1 migrations', () =>
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
// There are 40 docs in fixtures. Batch size configured to enforce 3 migration steps.
|
||||
batchSize: 15,
|
||||
},
|
||||
|
|
|
@ -67,7 +67,6 @@ function createRoot({ logFileName, hosts }: RootConfig) {
|
|||
},
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
batchSize: 100, // fixture contains 5000 docs
|
||||
},
|
||||
logging: {
|
||||
|
|
|
@ -67,7 +67,6 @@ async function createRoot({ logFileName }: CreateRootConfig) {
|
|||
},
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
batchSize: 100, // fixture contains 5000 docs
|
||||
},
|
||||
logging: {
|
||||
|
|
|
@ -95,7 +95,6 @@ function createRoot() {
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
},
|
||||
logging: {
|
||||
appenders: {
|
||||
|
|
|
@ -62,7 +62,6 @@ function createRoot() {
|
|||
{
|
||||
migrations: {
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
},
|
||||
logging: {
|
||||
appenders: {
|
||||
|
|
|
@ -45,7 +45,6 @@ describe('migrationsStateActionMachine', () => {
|
|||
pollInterval: 0,
|
||||
scrollDuration: '0s',
|
||||
skip: false,
|
||||
enableV2: true,
|
||||
retryAttempts: 5,
|
||||
},
|
||||
typeRegistry,
|
||||
|
|
|
@ -9,18 +9,16 @@
|
|||
import { IRouter } from '../../../http';
|
||||
import { catchAndReturnBoomErrors } from '../utils';
|
||||
import { deleteUnknownTypeObjects } from '../../deprecations';
|
||||
import { SavedObjectConfig } from '../../saved_objects_config';
|
||||
import { KibanaConfigType } from '../../../kibana_config';
|
||||
|
||||
interface RouteDependencies {
|
||||
config: SavedObjectConfig;
|
||||
kibanaConfig: KibanaConfigType;
|
||||
kibanaVersion: string;
|
||||
}
|
||||
|
||||
export const registerDeleteUnknownTypesRoute = (
|
||||
router: IRouter,
|
||||
{ config, kibanaConfig, kibanaVersion }: RouteDependencies
|
||||
{ kibanaConfig, kibanaVersion }: RouteDependencies
|
||||
) => {
|
||||
router.post(
|
||||
{
|
||||
|
@ -31,7 +29,6 @@ export const registerDeleteUnknownTypesRoute = (
|
|||
await deleteUnknownTypeObjects({
|
||||
esClient: context.core.elasticsearch.client,
|
||||
typeRegistry: context.core.savedObjects.typeRegistry,
|
||||
savedObjectsConfig: config,
|
||||
kibanaConfig,
|
||||
kibanaVersion,
|
||||
});
|
||||
|
|
|
@ -74,5 +74,5 @@ export function registerRoutes({
|
|||
const internalRouter = http.createRouter('/internal/saved_objects/');
|
||||
|
||||
registerMigrateRoute(internalRouter, migratorPromise);
|
||||
registerDeleteUnknownTypesRoute(internalRouter, { config, kibanaConfig, kibanaVersion });
|
||||
registerDeleteUnknownTypesRoute(internalRouter, { kibanaConfig, kibanaVersion });
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ import { elasticsearchServiceMock } from '../../../../../core/server/elasticsear
|
|||
import { typeRegistryMock } from '../../saved_objects_type_registry.mock';
|
||||
import { setupServer } from '../test_utils';
|
||||
import { KibanaConfigType } from '../../../kibana_config';
|
||||
import { SavedObjectConfig } from '../../saved_objects_config';
|
||||
import { SavedObjectsType } from 'kibana/server';
|
||||
|
||||
type SetupServerReturn = UnwrapPromise<ReturnType<typeof setupServer>>;
|
||||
|
@ -24,13 +23,6 @@ describe('POST /internal/saved_objects/deprecations/_delete_unknown_types', () =
|
|||
enabled: true,
|
||||
index: '.kibana',
|
||||
};
|
||||
const config: SavedObjectConfig = {
|
||||
maxImportExportSize: 10000,
|
||||
maxImportPayloadBytes: 24000000,
|
||||
migration: {
|
||||
enableV2: true,
|
||||
} as SavedObjectConfig['migration'],
|
||||
};
|
||||
|
||||
let server: SetupServerReturn['server'];
|
||||
let httpSetup: SetupServerReturn['httpSetup'];
|
||||
|
@ -54,7 +46,6 @@ describe('POST /internal/saved_objects/deprecations/_delete_unknown_types', () =
|
|||
registerDeleteUnknownTypesRoute(router, {
|
||||
kibanaVersion,
|
||||
kibanaConfig,
|
||||
config,
|
||||
});
|
||||
|
||||
await server.start();
|
||||
|
|
|
@ -22,7 +22,7 @@ describe('migrations config', function () {
|
|||
const { messages } = applyMigrationsDeprecations({ enableV2: true });
|
||||
expect(messages).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"migrations.enableV2\\" is deprecated and will be removed in an upcoming release without any further notice.",
|
||||
"You no longer need to configure \\"migrations.enableV2\\".",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -31,7 +31,7 @@ describe('migrations config', function () {
|
|||
const { messages } = applyMigrationsDeprecations({ enableV2: false });
|
||||
expect(messages).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"\\"migrations.enableV2\\" is deprecated and will be removed in an upcoming release without any further notice.",
|
||||
"You no longer need to configure \\"migrations.enableV2\\".",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
*/
|
||||
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import { ConfigDeprecationProvider } from '../config';
|
||||
import type { ServiceConfigDescriptor } from '../internal_types';
|
||||
import type { ConfigDeprecationProvider } from '../config';
|
||||
|
||||
const migrationSchema = schema.object({
|
||||
batchSize: schema.number({ defaultValue: 1_000 }),
|
||||
|
@ -16,29 +16,12 @@ const migrationSchema = schema.object({
|
|||
scrollDuration: schema.string({ defaultValue: '15m' }),
|
||||
pollInterval: schema.number({ defaultValue: 1_500 }),
|
||||
skip: schema.boolean({ defaultValue: false }),
|
||||
enableV2: schema.boolean({ defaultValue: true }),
|
||||
retryAttempts: schema.number({ defaultValue: 15 }),
|
||||
});
|
||||
|
||||
export type SavedObjectsMigrationConfigType = TypeOf<typeof migrationSchema>;
|
||||
|
||||
const migrationDeprecations: ConfigDeprecationProvider = () => [
|
||||
(settings, fromPath, addDeprecation) => {
|
||||
const migrationsConfig = settings[fromPath];
|
||||
if (migrationsConfig?.enableV2 !== undefined) {
|
||||
addDeprecation({
|
||||
configPath: `${fromPath}.enableV2`,
|
||||
message:
|
||||
'"migrations.enableV2" is deprecated and will be removed in an upcoming release without any further notice.',
|
||||
documentationUrl: 'https://ela.st/kbn-so-migration-v2',
|
||||
correctiveActions: {
|
||||
manualSteps: [`Remove "migrations.enableV2" from your kibana configs.`],
|
||||
},
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
},
|
||||
];
|
||||
const migrationDeprecations: ConfigDeprecationProvider = ({ unused }) => [unused('enableV2')];
|
||||
|
||||
export const savedObjectsMigrationConfig: ServiceConfigDescriptor<SavedObjectsMigrationConfigType> =
|
||||
{
|
||||
|
|
|
@ -18,63 +18,27 @@ describe('getIndexForType', () => {
|
|||
typeRegistry = typeRegistryMock.create();
|
||||
});
|
||||
|
||||
describe('when migV2 is enabled', () => {
|
||||
const migV2Enabled = true;
|
||||
|
||||
it('returns the correct index for a type specifying a custom index', () => {
|
||||
typeRegistry.getIndex.mockImplementation((type) => `.${type}-index`);
|
||||
expect(
|
||||
getIndexForType({
|
||||
type: 'foo',
|
||||
typeRegistry,
|
||||
defaultIndex,
|
||||
kibanaVersion,
|
||||
migV2Enabled,
|
||||
})
|
||||
).toEqual('.foo-index_8.0.0');
|
||||
});
|
||||
|
||||
it('returns the correct index for a type not specifying a custom index', () => {
|
||||
typeRegistry.getIndex.mockImplementation((type) => undefined);
|
||||
expect(
|
||||
getIndexForType({
|
||||
type: 'foo',
|
||||
typeRegistry,
|
||||
defaultIndex,
|
||||
kibanaVersion,
|
||||
migV2Enabled,
|
||||
})
|
||||
).toEqual('.kibana_8.0.0');
|
||||
});
|
||||
it('returns the correct index for a type specifying a custom index', () => {
|
||||
typeRegistry.getIndex.mockImplementation((type) => `.${type}-index`);
|
||||
expect(
|
||||
getIndexForType({
|
||||
type: 'foo',
|
||||
typeRegistry,
|
||||
defaultIndex,
|
||||
kibanaVersion,
|
||||
})
|
||||
).toEqual('.foo-index_8.0.0');
|
||||
});
|
||||
|
||||
describe('when migV2 is disabled', () => {
|
||||
const migV2Enabled = false;
|
||||
|
||||
it('returns the correct index for a type specifying a custom index', () => {
|
||||
typeRegistry.getIndex.mockImplementation((type) => `.${type}-index`);
|
||||
expect(
|
||||
getIndexForType({
|
||||
type: 'foo',
|
||||
typeRegistry,
|
||||
defaultIndex,
|
||||
kibanaVersion,
|
||||
migV2Enabled,
|
||||
})
|
||||
).toEqual('.foo-index');
|
||||
});
|
||||
|
||||
it('returns the correct index for a type not specifying a custom index', () => {
|
||||
typeRegistry.getIndex.mockImplementation((type) => undefined);
|
||||
expect(
|
||||
getIndexForType({
|
||||
type: 'foo',
|
||||
typeRegistry,
|
||||
defaultIndex,
|
||||
kibanaVersion,
|
||||
migV2Enabled,
|
||||
})
|
||||
).toEqual('.kibana');
|
||||
});
|
||||
it('returns the correct index for a type not specifying a custom index', () => {
|
||||
typeRegistry.getIndex.mockImplementation((type) => undefined);
|
||||
expect(
|
||||
getIndexForType({
|
||||
type: 'foo',
|
||||
typeRegistry,
|
||||
defaultIndex,
|
||||
kibanaVersion,
|
||||
})
|
||||
).toEqual('.kibana_8.0.0');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,7 +11,6 @@ import { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry';
|
|||
interface GetIndexForTypeOptions {
|
||||
type: string;
|
||||
typeRegistry: ISavedObjectTypeRegistry;
|
||||
migV2Enabled: boolean;
|
||||
kibanaVersion: string;
|
||||
defaultIndex: string;
|
||||
}
|
||||
|
@ -19,18 +18,8 @@ interface GetIndexForTypeOptions {
|
|||
export const getIndexForType = ({
|
||||
type,
|
||||
typeRegistry,
|
||||
migV2Enabled,
|
||||
defaultIndex,
|
||||
kibanaVersion,
|
||||
}: GetIndexForTypeOptions): string => {
|
||||
// TODO migrationsV2: Remove once we remove migrations v1
|
||||
// This is a hacky, but it required the least amount of changes to
|
||||
// existing code to support a migrations v2 index. Long term we would
|
||||
// want to always use the type registry to resolve a type's index
|
||||
// (including the default index).
|
||||
if (migV2Enabled) {
|
||||
return `${typeRegistry.getIndex(type) || defaultIndex}_${kibanaVersion}`;
|
||||
} else {
|
||||
return typeRegistry.getIndex(type) || defaultIndex;
|
||||
}
|
||||
return `${typeRegistry.getIndex(type) || defaultIndex}_${kibanaVersion}`;
|
||||
};
|
||||
|
|
|
@ -613,12 +613,18 @@ describe('SavedObjectsRepository', () => {
|
|||
|
||||
it(`should use default index`, async () => {
|
||||
await bulkCreateSuccess([obj1, obj2]);
|
||||
expectClientCallArgsAction([obj1, obj2], { method: 'create', _index: '.kibana-test' });
|
||||
expectClientCallArgsAction([obj1, obj2], {
|
||||
method: 'create',
|
||||
_index: '.kibana-test_8.0.0-testing',
|
||||
});
|
||||
});
|
||||
|
||||
it(`should use custom index`, async () => {
|
||||
await bulkCreateSuccess([obj1, obj2].map((x) => ({ ...x, type: CUSTOM_INDEX_TYPE })));
|
||||
expectClientCallArgsAction([obj1, obj2], { method: 'create', _index: 'custom' });
|
||||
expectClientCallArgsAction([obj1, obj2], {
|
||||
method: 'create',
|
||||
_index: 'custom_8.0.0-testing',
|
||||
});
|
||||
});
|
||||
|
||||
it(`prepends namespace to the id when providing namespace for single-namespace type`, async () => {
|
||||
|
@ -2092,7 +2098,7 @@ describe('SavedObjectsRepository', () => {
|
|||
it(`should use default index`, async () => {
|
||||
await createSuccess(type, attributes, { id });
|
||||
expect(client.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ index: '.kibana-test' }),
|
||||
expect.objectContaining({ index: '.kibana-test_8.0.0-testing' }),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
|
@ -2100,7 +2106,7 @@ describe('SavedObjectsRepository', () => {
|
|||
it(`should use custom index`, async () => {
|
||||
await createSuccess(CUSTOM_INDEX_TYPE, attributes, { id });
|
||||
expect(client.create).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ index: 'custom' }),
|
||||
expect.objectContaining({ index: 'custom_8.0.0-testing' }),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
|
@ -2680,7 +2686,9 @@ describe('SavedObjectsRepository', () => {
|
|||
it(`should use all indices for types that are not namespace-agnostic`, async () => {
|
||||
await deleteByNamespaceSuccess(namespace);
|
||||
expect(client.updateByQuery).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ index: ['.kibana-test', 'custom'] }),
|
||||
expect.objectContaining({
|
||||
index: ['.kibana-test_8.0.0-testing', 'custom_8.0.0-testing'],
|
||||
}),
|
||||
expect.anything()
|
||||
);
|
||||
});
|
||||
|
@ -2774,7 +2782,7 @@ describe('SavedObjectsRepository', () => {
|
|||
await removeReferencesToSuccess();
|
||||
expect(client.updateByQuery).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
index: ['.kibana-test', 'custom'],
|
||||
index: ['.kibana-test_8.0.0-testing', 'custom_8.0.0-testing'],
|
||||
}),
|
||||
expect.anything()
|
||||
);
|
||||
|
|
|
@ -2089,7 +2089,6 @@ export class SavedObjectsRepository {
|
|||
defaultIndex: this._index,
|
||||
typeRegistry: this._registry,
|
||||
kibanaVersion: this._migrator.kibanaVersion,
|
||||
migV2Enabled: this._migrator.soMigrationsConfig.enableV2,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -94,7 +94,6 @@ kibana_vars=(
|
|||
map.tilemap.url
|
||||
migrations.batchSize
|
||||
migrations.maxBatchSizeBytes
|
||||
migrations.enableV2
|
||||
migrations.pollInterval
|
||||
migrations.retryAttempts
|
||||
migrations.scrollDuration
|
||||
|
|
|
@ -43,7 +43,6 @@ async function config({ readConfigFile }: FtrConfigProviderContext) {
|
|||
`--uiSettings.overrides.theme:darkMode=true`,
|
||||
`--elasticsearch.username=kibana_system`,
|
||||
`--elasticsearch.password=changeme`,
|
||||
'--migrations.enableV2=false',
|
||||
'--xpack.reporting.enabled=false',
|
||||
],
|
||||
},
|
||||
|
|
|
@ -11,22 +11,13 @@ import { createTestConfig, CreateTestConfig } from '../common/config';
|
|||
const apmFtrConfigs = {
|
||||
basic: {
|
||||
license: 'basic' as const,
|
||||
kibanaConfig: {
|
||||
// disable v2 migrations to prevent issue where kibana index is deleted
|
||||
// during a migration
|
||||
'migrations.enableV2': 'false',
|
||||
},
|
||||
},
|
||||
trial: {
|
||||
license: 'trial' as const,
|
||||
kibanaConfig: {
|
||||
'migrations.enableV2': 'false',
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
license: 'trial' as const,
|
||||
kibanaConfig: {
|
||||
'migrations.enableV2': 'false',
|
||||
'xpack.ruleRegistry.write.enabled': 'true',
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue