From 2ce5baa8009276a4e162cf60a73ade2558a8fe90 Mon Sep 17 00:00:00 2001 From: Gerard Soldevila Date: Mon, 12 Dec 2022 17:22:51 +0100 Subject: [PATCH 1/4] Prevent future convertToMultiNamespaceType migrations --- .../test_helpers/repository.test.common.ts | 2 ++ .../src/core/document_migrator.test.ts | 12 ++++------ .../src/core/document_migrator.ts | 24 +++++++------------ .../src/kibana_migrator.ts | 5 ++++ 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/test_helpers/repository.test.common.ts b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/test_helpers/repository.test.common.ts index 600b1e967c677..fd96f9df87f83 100644 --- a/packages/core/saved-objects/core-saved-objects-api-server-internal/src/test_helpers/repository.test.common.ts +++ b/packages/core/saved-objects/core-saved-objects-api-server-internal/src/test_helpers/repository.test.common.ts @@ -97,6 +97,7 @@ export const expectErrorInvalidType = (obj: TypeIdTuple, overrides?: Record { return new DocumentMigrator({ typeRegistry: registry, kibanaVersion: KIBANA_VERSION, + convertVersion: ALLOWED_CONVERT_VERSION, log: loggerMock.create(), }); }; diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/document_migrator.test.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/document_migrator.test.ts index a0dd1cfddc3a4..f8d2948510531 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/document_migrator.test.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/document_migrator.test.ts @@ -55,7 +55,6 @@ describe('DocumentMigrator', () => { return { kibanaVersion, typeRegistry: createRegistry(), - minimumConvertVersion: '0.0.0', // no minimum version unless we specify it for a test case log: mockLogger, }; } @@ -63,6 +62,7 @@ describe('DocumentMigrator', () => { describe('validation', () => { const createDefinition = (migrations: any) => ({ kibanaVersion: '3.2.3', + convertVersion: '8.0.0', typeRegistry: createRegistry({ name: 'foo', migrations: migrations as any, @@ -163,7 +163,6 @@ describe('DocumentMigrator', () => { name: 'foo', convertToMultiNamespaceTypeVersion: 'bar', }), - minimumConvertVersion: '0.0.0', log: mockLogger, }; expect(() => new DocumentMigrator(invalidDefinition)).toThrow( @@ -179,7 +178,6 @@ describe('DocumentMigrator', () => { convertToMultiNamespaceTypeVersion: 'bar', namespaceType: 'multiple', }), - minimumConvertVersion: '0.0.0', log: mockLogger, }; expect(() => new DocumentMigrator(invalidDefinition)).toThrow( @@ -187,7 +185,7 @@ describe('DocumentMigrator', () => { ); }); - it('validates convertToMultiNamespaceTypeVersion is not less than the minimum allowed version', () => { + it('validates convertToMultiNamespaceTypeVersion matches the convertVersion, if specified', () => { const invalidDefinition = { kibanaVersion: '3.2.3', typeRegistry: createRegistry({ @@ -195,11 +193,11 @@ describe('DocumentMigrator', () => { convertToMultiNamespaceTypeVersion: '3.2.4', namespaceType: 'multiple', }), - // not using a minimumConvertVersion parameter, the default is 8.0.0 + convertVersion: '3.2.3', log: mockLogger, }; expect(() => new DocumentMigrator(invalidDefinition)).toThrowError( - `Invalid convertToMultiNamespaceTypeVersion for type foo. Value '3.2.4' cannot be less than '8.0.0'.` + `Invalid convertToMultiNamespaceTypeVersion for type foo. Value '3.2.4' cannot be any other than '3.2.3'.` ); }); @@ -211,7 +209,6 @@ describe('DocumentMigrator', () => { convertToMultiNamespaceTypeVersion: '3.2.4', namespaceType: 'multiple', }), - minimumConvertVersion: '0.0.0', log: mockLogger, }; expect(() => new DocumentMigrator(invalidDefinition)).toThrowError( @@ -227,7 +224,6 @@ describe('DocumentMigrator', () => { convertToMultiNamespaceTypeVersion: '3.1.1', namespaceType: 'multiple', }), - minimumConvertVersion: '0.0.0', log: mockLogger, }; expect(() => new DocumentMigrator(invalidDefinition)).toThrowError( diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/document_migrator.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/document_migrator.ts index 1040699a99e9d..c737489dd2231 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/document_migrator.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/core/document_migrator.ts @@ -66,8 +66,6 @@ import { import { MigrationLogger } from './migration_logger'; import { TransformSavedObjectDocumentError } from '.'; -const DEFAULT_MINIMUM_CONVERT_VERSION = '8.0.0'; - export type MigrateFn = (doc: SavedObjectUnsanitizedDoc) => SavedObjectUnsanitizedDoc; export type MigrateAndConvertFn = (doc: SavedObjectUnsanitizedDoc) => SavedObjectUnsanitizedDoc[]; @@ -95,7 +93,7 @@ interface TransformOptions { interface DocumentMigratorOptions { kibanaVersion: string; typeRegistry: ISavedObjectTypeRegistry; - minimumConvertVersion?: string; + convertVersion?: string; log: Logger; } @@ -142,7 +140,7 @@ export interface VersionedTransformer { * A concrete implementation of the VersionedTransformer interface. */ export class DocumentMigrator implements VersionedTransformer { - private documentMigratorOptions: Omit; + private documentMigratorOptions: Omit; private migrations?: ActiveMigrations; private transformDoc?: ApplyTransformsFn; @@ -152,17 +150,12 @@ export class DocumentMigrator implements VersionedTransformer { * @param {DocumentMigratorOptions} opts * @prop {string} kibanaVersion - The current version of Kibana * @prop {SavedObjectTypeRegistry} typeRegistry - The type registry to get type migrations from - * @prop {string} minimumConvertVersion - The minimum version of Kibana in which documents can be converted to multi-namespace types + * @prop {string} convertVersion - The version of Kibana in which documents can be converted to multi-namespace types * @prop {Logger} log - The migration logger * @memberof DocumentMigrator */ - constructor({ - typeRegistry, - kibanaVersion, - minimumConvertVersion = DEFAULT_MINIMUM_CONVERT_VERSION, - log, - }: DocumentMigratorOptions) { - validateMigrationDefinition(typeRegistry, kibanaVersion, minimumConvertVersion); + constructor({ typeRegistry, kibanaVersion, convertVersion, log }: DocumentMigratorOptions) { + validateMigrationDefinition(typeRegistry, kibanaVersion, convertVersion); this.documentMigratorOptions = { typeRegistry, kibanaVersion, log }; } @@ -300,7 +293,7 @@ function validateMigrationsMapObject( function validateMigrationDefinition( registry: ISavedObjectTypeRegistry, kibanaVersion: string, - minimumConvertVersion: string + convertVersion?: string ) { function assertObjectOrFunction(entity: any, prefix: string) { if (!entity || (typeof entity !== 'function' && typeof entity !== 'object')) { @@ -321,9 +314,9 @@ function validateMigrationDefinition( throw new Error( `Invalid convertToMultiNamespaceTypeVersion for type ${type}. Expected value to be a semver, but got '${convertToMultiNamespaceTypeVersion}'.` ); - } else if (Semver.lt(convertToMultiNamespaceTypeVersion, minimumConvertVersion)) { + } else if (convertVersion && Semver.neq(convertToMultiNamespaceTypeVersion, convertVersion)) { throw new Error( - `Invalid convertToMultiNamespaceTypeVersion for type ${type}. Value '${convertToMultiNamespaceTypeVersion}' cannot be less than '${minimumConvertVersion}'.` + `Invalid convertToMultiNamespaceTypeVersion for type ${type}. Value '${convertToMultiNamespaceTypeVersion}' cannot be any other than '${convertVersion}'.` ); } else if (Semver.gt(convertToMultiNamespaceTypeVersion, kibanaVersion)) { throw new Error( @@ -345,6 +338,7 @@ function validateMigrationDefinition( ); } if (convertToMultiNamespaceTypeVersion) { + // CHECKPOINT 1 assertValidConvertToMultiNamespaceType( namespaceType, convertToMultiNamespaceTypeVersion, diff --git a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts index 3432021249886..58a5a741a6163 100644 --- a/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts +++ b/packages/core/saved-objects/core-saved-objects-migration-server-internal/src/kibana_migrator.ts @@ -37,6 +37,10 @@ import { createIndexMap } from './core/build_index_map'; import { runResilientMigrator } from './run_resilient_migrator'; import { migrateRawDocsSafely } from './core/migrate_raw_docs'; +// ensure plugins don't try to convert SO namespaceTypes after 8.0.0 +// see https://github.com/elastic/kibana/issues/147344 +const ALLOWED_CONVERT_VERSION = '8.0.0'; + export interface KibanaMigratorOptions { client: ElasticsearchClient; typeRegistry: ISavedObjectTypeRegistry; @@ -92,6 +96,7 @@ export class KibanaMigrator implements IKibanaMigrator { this.kibanaVersion = kibanaVersion; this.documentMigrator = new DocumentMigrator({ kibanaVersion: this.kibanaVersion, + convertVersion: ALLOWED_CONVERT_VERSION, typeRegistry, log: this.log, }); From ec69b92885c9b334edfd24d57833f1dbb4549783 Mon Sep 17 00:00:00 2001 From: Gerard Soldevila Date: Wed, 21 Dec 2022 12:14:31 +0100 Subject: [PATCH 2/4] Address PR comments --- docs/developer/advanced/sharing-saved-objects.asciidoc | 1 + .../saved-objects/core-saved-objects-server/src/migration.ts | 1 + .../core-saved-objects-server/src/saved_objects_type.ts | 1 + 3 files changed, 3 insertions(+) diff --git a/docs/developer/advanced/sharing-saved-objects.asciidoc b/docs/developer/advanced/sharing-saved-objects.asciidoc index 6121201bb07c5..5b7f6e7158ad3 100644 --- a/docs/developer/advanced/sharing-saved-objects.asciidoc +++ b/docs/developer/advanced/sharing-saved-objects.asciidoc @@ -4,6 +4,7 @@ This guide describes the "Sharing saved objects" effort, and the breaking changes that plugin developers need to be aware of for the planned 8.0 release of {kib}. It also describes how developers can take advantage of this feature. +`From *8.7.0*, as a step towards Zero-Down-Time upgrades, plugins are no longer allowed to switch to shareable saved objects.` [[sharing-saved-objects-overview]] === Overview diff --git a/packages/core/saved-objects/core-saved-objects-server/src/migration.ts b/packages/core/saved-objects/core-saved-objects-server/src/migration.ts index 4634edef3d2bf..9ac9444a8dbee 100644 --- a/packages/core/saved-objects/core-saved-objects-server/src/migration.ts +++ b/packages/core/saved-objects/core-saved-objects-server/src/migration.ts @@ -76,6 +76,7 @@ export interface SavedObjectMigrationContext { readonly migrationVersion: string; /** * The version in which this object type is being converted to a multi-namespace type + * @deprecated Converting to multi-namespace clashes with the ZDT requirement for serverless */ readonly convertToMultiNamespaceTypeVersion?: string; /** diff --git a/packages/core/saved-objects/core-saved-objects-server/src/saved_objects_type.ts b/packages/core/saved-objects/core-saved-objects-server/src/saved_objects_type.ts index e36212e7913f3..8c5ff2b9fa542 100644 --- a/packages/core/saved-objects/core-saved-objects-server/src/saved_objects_type.ts +++ b/packages/core/saved-objects/core-saved-objects-server/src/saved_objects_type.ts @@ -113,6 +113,7 @@ export interface SavedObjectsType { * ``` * * Note: migration function(s) can be optionally specified for any of these versions and will not interfere with the conversion process. + * @deprecated Converting to multi-namespace clashes with the ZDT requirement for serverless */ convertToMultiNamespaceTypeVersion?: string; /** From 5d0c374a197f68b65f4672ada4d2cfdc30eb5989 Mon Sep 17 00:00:00 2001 From: Gerard Soldevila Date: Wed, 21 Dec 2022 12:36:21 +0100 Subject: [PATCH 3/4] Update docs --- docs/developer/advanced/sharing-saved-objects.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/developer/advanced/sharing-saved-objects.asciidoc b/docs/developer/advanced/sharing-saved-objects.asciidoc index 5b7f6e7158ad3..8695f8df59df7 100644 --- a/docs/developer/advanced/sharing-saved-objects.asciidoc +++ b/docs/developer/advanced/sharing-saved-objects.asciidoc @@ -4,7 +4,7 @@ This guide describes the "Sharing saved objects" effort, and the breaking changes that plugin developers need to be aware of for the planned 8.0 release of {kib}. It also describes how developers can take advantage of this feature. -`From *8.7.0*, as a step towards Zero-Down-Time upgrades, plugins are no longer allowed to switch to shareable saved objects.` +Whilst new saved object types can still be defined as 'multiple', existing plugins are no longer allowed to switch to shareable saved objects. [[sharing-saved-objects-overview]] === Overview From 6fbdfdd0c8ae4be6b9b2378527bbbca36bdd6f43 Mon Sep 17 00:00:00 2001 From: Gerard Soldevila Date: Wed, 21 Dec 2022 12:38:40 +0100 Subject: [PATCH 4/4] Update docs, take 2 --- docs/developer/advanced/sharing-saved-objects.asciidoc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/developer/advanced/sharing-saved-objects.asciidoc b/docs/developer/advanced/sharing-saved-objects.asciidoc index 8695f8df59df7..b221dbc275dd0 100644 --- a/docs/developer/advanced/sharing-saved-objects.asciidoc +++ b/docs/developer/advanced/sharing-saved-objects.asciidoc @@ -4,7 +4,9 @@ This guide describes the "Sharing saved objects" effort, and the breaking changes that plugin developers need to be aware of for the planned 8.0 release of {kib}. It also describes how developers can take advantage of this feature. -Whilst new saved object types can still be defined as 'multiple', existing plugins are no longer allowed to switch to shareable saved objects. +From 8.7.0, as a step towards _zero downtime upgrades_, plugins are no longer allowed to update existing single space saved object types to become shareable. +Note that new saved object types can still be defined as `'multiple'` or `'multiple-isolated'`. + [[sharing-saved-objects-overview]] === Overview