diff --git a/dev_docs/tutorials/saved_objects.mdx b/dev_docs/tutorials/saved_objects.mdx index 53ebdb0caa7ef..71b99e2ae5e7e 100644 --- a/dev_docs/tutorials/saved_objects.mdx +++ b/dev_docs/tutorials/saved_objects.mdx @@ -19,6 +19,7 @@ import { SavedObjectsType } from 'src/core/server'; export const dashboardVisualization: SavedObjectsType = { name: 'dashboard_visualization', [1] hidden: true, [3] + switchToModelVersionAt: '8.10.0', // this is the default, feel free to omit it unless you intend to switch to using model versions before 8.10.0 namespaceType: 'multiple-isolated', [2] mappings: { dynamic: false, diff --git a/docs/extend/saved-objects-service.md b/docs/extend/saved-objects-service.md index b757a126d9e2d..d883aafc2a0b5 100644 --- a/docs/extend/saved-objects-service.md +++ b/docs/extend/saved-objects-service.md @@ -38,6 +38,7 @@ export const dashboardVisualization: SavedObjectsType = { name: 'dashboard_visualization', <1> hidden: true, namespaceType: 'multiple-isolated', <2> + switchToModelVersionAt: '8.10.0', modelVersions: { 1: modelVersion1, 2: modelVersion2, @@ -164,6 +165,7 @@ That way: - SO type versions are decoupled from stack versioning - SO type versi ```ts const myType: SavedObjectsType = { name: 'test', + switchToModelVersionAt: '8.10.0', modelVersions: { 1: modelVersion1, // valid: start with version 1 2: modelVersion2, // valid: no gap between versions @@ -177,6 +179,7 @@ const myType: SavedObjectsType = { ```ts const myType: SavedObjectsType = { name: 'test', + switchToModelVersionAt: '8.10.0', modelVersions: { 2: modelVersion2, // invalid: first version must be 1 4: modelVersion3, // invalid: skipped version 3 @@ -195,6 +198,7 @@ const myType: SavedObjectsType = { ```ts const myType: SavedObjectsType = { name: 'test', + switchToModelVersionAt: '8.10.0', modelVersions: { 1: { changes: [ @@ -425,6 +429,7 @@ The definition of the type at version 1 would look like: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { // initial (and current) model version 1: { @@ -481,6 +486,7 @@ The full type definition after the addition of the new model version: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { 1: { changes: [], @@ -569,6 +575,7 @@ the full type definition after the addition of the model version 2 would be: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { 1: { changes: [ @@ -664,6 +671,7 @@ The full type definition would look like: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { 1: { changes: [ @@ -734,6 +742,7 @@ The definition of the type at version 1 would look like: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { // initial (and current) model version 1: { @@ -798,6 +807,7 @@ The full type definition after the addition of the new model version: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { // initial (and current) model version 1: { @@ -865,6 +875,7 @@ The full type definition after the data removal would look like: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { // initial (and current) model version 1: { diff --git a/src/core/packages/saved-objects/api-server-internal/src/lib/apis/helpers/validation_fixtures.ts b/src/core/packages/saved-objects/api-server-internal/src/lib/apis/helpers/validation_fixtures.ts index d9bccc009c211..419e50bf57952 100644 --- a/src/core/packages/saved-objects/api-server-internal/src/lib/apis/helpers/validation_fixtures.ts +++ b/src/core/packages/saved-objects/api-server-internal/src/lib/apis/helpers/validation_fixtures.ts @@ -30,6 +30,7 @@ export const typedef: Partial = { count: schema.number(), }), }, + switchToModelVersionAt: '8.10.0', }; export const typedef1: Partial = { @@ -52,6 +53,7 @@ export const typedef1: Partial = { count: schema.number(), }), }, + switchToModelVersionAt: '8.10.0', modelVersions: { '1': { changes: [ @@ -94,6 +96,7 @@ export const typedef2: Partial = { foo: schema.string(), }), }, + switchToModelVersionAt: '8.10.0', modelVersions: { '1': { changes: [ diff --git a/src/core/packages/saved-objects/base-server-internal/src/model_version/version_map.test.ts b/src/core/packages/saved-objects/base-server-internal/src/model_version/version_map.test.ts index 6b3c472680e72..a0e5bd3fa9bd3 100644 --- a/src/core/packages/saved-objects/base-server-internal/src/model_version/version_map.test.ts +++ b/src/core/packages/saved-objects/base-server-internal/src/model_version/version_map.test.ts @@ -206,7 +206,7 @@ describe('ModelVersion map utilities', () => { }); describe('getCurrentVirtualVersion', () => { - it('returns the latest registered migration if modelVersions is not defined', () => { + it('returns the latest registered migration if switchToModelVersionAt is unset', () => { expect( getCurrentVirtualVersion( buildType({ @@ -214,15 +214,19 @@ describe('ModelVersion map utilities', () => { '7.17.2': dummyMigration, '8.6.0': dummyMigration, }, + modelVersions: { + 1: dummyModelVersion(), + }, }) ) ).toEqual('8.6.0'); }); - it('returns the virtual version of the latest model version if the type has modelVersions', () => { + it('returns the virtual version of the latest model version if switchToModelVersionAt is set', () => { expect( getCurrentVirtualVersion( buildType({ + switchToModelVersionAt: '8.7.0', migrations: { '7.17.2': dummyMigration, '8.6.0': dummyMigration, @@ -242,6 +246,7 @@ describe('ModelVersion map utilities', () => { getVirtualVersionMap([ buildType({ name: 'foo', + switchToModelVersionAt: '8.7.0', migrations: { '7.17.2': dummyMigration, '8.6.0': dummyMigration, @@ -256,11 +261,16 @@ describe('ModelVersion map utilities', () => { '7.17.2': dummyMigration, '8.6.0': dummyMigration, }, + modelVersions: { + 1: dummyModelVersion(), + }, }), buildType({ name: 'dolly', - modelVersions: { - 0: dummyModelVersion(), + switchToModelVersionAt: '8.7.0', + migrations: { + '7.17.2': dummyMigration, + '8.6.0': dummyMigration, }, }), ]) @@ -334,7 +344,7 @@ describe('ModelVersion map utilities', () => { }); describe('getLatestMappingsModelVersion', () => { - it('returns the latest registered migration if no model versions are defined', () => { + it('returns the latest registered migration if switchToModelVersionAt is unset', () => { expect( getLatestMappingsModelVersion( buildType({ @@ -342,15 +352,20 @@ describe('ModelVersion map utilities', () => { '7.17.2': dummyMigration, '8.6.0': dummyMigration, }, + modelVersions: { + 1: dummyModelVersionWithMappingsChanges(), + 2: dummyModelVersion(), + }, }) ) ).toEqual('8.6.0'); }); - it('returns the virtual version of the latest model version if model versions are defined', () => { + it('returns the virtual version of the latest model version if switchToModelVersionAt is set', () => { expect( getLatestMappingsModelVersion( buildType({ + switchToModelVersionAt: '8.7.0', migrations: { '7.17.2': dummyMigration, '8.6.0': dummyMigration, @@ -371,6 +386,7 @@ describe('ModelVersion map utilities', () => { getLatestMappingsVirtualVersionMap([ buildType({ name: 'foo', + switchToModelVersionAt: '8.7.0', migrations: { '7.17.2': dummyMigration, '8.6.0': dummyMigration, @@ -386,14 +402,18 @@ describe('ModelVersion map utilities', () => { '7.17.2': dummyMigration, '8.6.0': dummyMigration, }, + modelVersions: { + 1: dummyModelVersionWithMappingsChanges(), + 2: dummyModelVersion(), + }, }), buildType({ name: 'dolly', + switchToModelVersionAt: '8.7.0', migrations: { '7.17.2': dummyMigration, '8.6.0': dummyMigration, }, - modelVersions: { 0: dummyModelVersion() }, }), ]) ).toEqual({ diff --git a/src/core/packages/saved-objects/base-server-internal/src/model_version/version_map.ts b/src/core/packages/saved-objects/base-server-internal/src/model_version/version_map.ts index d3dcd479de6bf..64ce3d29ec1bb 100644 --- a/src/core/packages/saved-objects/base-server-internal/src/model_version/version_map.ts +++ b/src/core/packages/saved-objects/base-server-internal/src/model_version/version_map.ts @@ -64,11 +64,12 @@ export const getModelVersionMapForTypes = (types: SavedObjectsType[]): ModelVers /** * Returns the current virtual version for the given type. - * It will either be the latest model version or the latest - * migration version for the type if model versions have not been declared. + * It will either be the latest model version if the type + * already switched to using them (switchToModelVersionAt is set), + * or the latest migration version for the type otherwise. */ export const getCurrentVirtualVersion = (type: SavedObjectsType): string => { - if (type.modelVersions) { + if (type.switchToModelVersionAt) { const modelVersion = getLatestModelVersion(type); return modelVersionToVirtualVersion(modelVersion); } else { @@ -105,11 +106,12 @@ export const getLatestMappingsVersionNumber = (type: SavedObjectsType): number = /** * Returns the latest model version that includes changes in the mappings, for the given type. - * It will either be a model version or the latest migration version - * if no changed were introduced after enforcing the switch to model versions. + * It will either be a model version if the type + * already switched to using them (switchToModelVersionAt is set), + * or the latest migration version for the type otherwise. */ export const getLatestMappingsModelVersion = (type: SavedObjectsType): string => { - if (type.modelVersions) { + if (type.switchToModelVersionAt) { const modelVersion = getLatestMappingsVersionNumber(type); return modelVersionToVirtualVersion(modelVersion); } else { diff --git a/src/core/packages/saved-objects/migration-server-internal/src/document_migrator/document_migrator.test.ts b/src/core/packages/saved-objects/migration-server-internal/src/document_migrator/document_migrator.test.ts index e12a6be1655d7..12a28f8a818f1 100644 --- a/src/core/packages/saved-objects/migration-server-internal/src/document_migrator/document_migrator.test.ts +++ b/src/core/packages/saved-objects/migration-server-internal/src/document_migrator/document_migrator.test.ts @@ -1415,6 +1415,7 @@ describe('DocumentMigrator', () => { const fooType = createType({ name: 'foo', + switchToModelVersionAt: '8.5.0', modelVersions: { 1: { changes: [], @@ -1457,6 +1458,7 @@ describe('DocumentMigrator', () => { const fooType = createType({ name: 'foo', + switchToModelVersionAt: '8.5.0', modelVersions: { 1: { changes: [], diff --git a/src/core/packages/saved-objects/migration-server-internal/src/document_migrator/validate_migration.test.ts b/src/core/packages/saved-objects/migration-server-internal/src/document_migrator/validate_migration.test.ts index c970c13ae1b28..9f32634c2121e 100644 --- a/src/core/packages/saved-objects/migration-server-internal/src/document_migrator/validate_migration.test.ts +++ b/src/core/packages/saved-objects/migration-server-internal/src/document_migrator/validate_migration.test.ts @@ -112,70 +112,75 @@ describe('validateTypeMigrations', () => { expect(() => validate({ type })).not.toThrow(); }); - describe('effect of globalSwitchToModelVersionAt', () => { - it('throws if a migration is specified for a version superior to globalSwitchToModelVersionAt', () => { + describe('when switchToModelVersionAt is specified', () => { + it('throws if a migration is specified for a version superior to switchToModelVersionAt', () => { const type = createType({ name: 'foo', + switchToModelVersionAt: '8.9.0', migrations: { - '8.11.0': jest.fn(), + '8.10.0': jest.fn(), }, }); expect(() => - validate({ type, kibanaVersion: '8.11.0' }) + validate({ type, kibanaVersion: '8.10.0' }) ).toThrowErrorMatchingInlineSnapshot( - `"Migration for type foo for version 8.11.0 registered after globalSwitchToModelVersionAt (8.10.0)"` + `"Migration for type foo for version 8.10.0 registered after switchToModelVersionAt (8.9.0)"` ); }); - it('throws if a schema is specified for a version superior to globalSwitchToModelVersionAt', () => { + it('throws if a schema is specified for a version superior to switchToModelVersionAt', () => { const type = createType({ name: 'foo', + switchToModelVersionAt: '8.9.0', schemas: { - '8.11.0': schema.object({ name: schema.string() }), + '8.10.0': schema.object({ name: schema.string() }), }, }); expect(() => - validate({ type, kibanaVersion: '8.11.0' }) + validate({ type, kibanaVersion: '8.10.0' }) ).toThrowErrorMatchingInlineSnapshot( - `"Schema for type foo for version 8.11.0 registered after globalSwitchToModelVersionAt (8.10.0)"` + `"Schema for type foo for version 8.10.0 registered after switchToModelVersionAt (8.9.0)"` ); }); - it('throws if a migration is specified for a version equal to globalSwitchToModelVersionAt', () => { + it('throws if a migration is specified for a version equal to switchToModelVersionAt', () => { const type = createType({ name: 'foo', + switchToModelVersionAt: '8.9.0', migrations: { - '8.11.0': jest.fn(), + '8.9.0': jest.fn(), }, }); expect(() => - validate({ type, kibanaVersion: '8.11.0' }) + validate({ type, kibanaVersion: '8.10.0' }) ).toThrowErrorMatchingInlineSnapshot( - `"Migration for type foo for version 8.11.0 registered after globalSwitchToModelVersionAt (8.10.0)"` + `"Migration for type foo for version 8.9.0 registered after switchToModelVersionAt (8.9.0)"` ); }); - it('throws if a schema is specified for a version equal to globalSwitchToModelVersionAt', () => { + it('throws if a schema is specified for a version equal to switchToModelVersionAt', () => { const type = createType({ name: 'foo', + switchToModelVersionAt: '8.9.0', schemas: { - '8.10.0': schema.object({ name: schema.string() }), + '8.9.0': schema.object({ name: schema.string() }), }, }); expect(() => validate({ type, kibanaVersion: '8.10.0' }) ).toThrowErrorMatchingInlineSnapshot( - `"Schema for type foo for version 8.10.0 registered after globalSwitchToModelVersionAt (8.10.0)"` + `"Schema for type foo for version 8.9.0 registered after switchToModelVersionAt (8.9.0)"` ); }); - it('does not throw if a migration is specified for a version inferior to globalSwitchToModelVersionAt', () => { + it('does not throw if a migration is specified for a version inferior to switchToModelVersionAt', () => { const type = createType({ name: 'foo', + switchToModelVersionAt: '8.9.0', migrations: { '8.7.0': jest.fn(), }, @@ -184,9 +189,10 @@ describe('validateTypeMigrations', () => { expect(() => validate({ type, kibanaVersion: '8.10.0' })).not.toThrow(); }); - it('does not throw if a schema is specified for a version inferior to globalSwitchToModelVersionAt', () => { + it('does not throw if a schema is specified for a version inferior to switchToModelVersionAt', () => { const type = createType({ name: 'foo', + switchToModelVersionAt: '8.9.0', schemas: { '8.7.0': schema.object({ name: schema.string() }), }, @@ -197,8 +203,32 @@ describe('validateTypeMigrations', () => { }); }); + describe('switchToModelVersionAt', () => { + it('throws if the specified version is not a valid semver', () => { + const type = createType({ + name: 'foo', + switchToModelVersionAt: 'foo', + }); + + expect(() => validate({ type })).toThrowErrorMatchingInlineSnapshot( + `"Type foo: invalid version specified for switchToModelVersionAt: foo"` + ); + }); + + it('throws if the specified version defines a patch version > 0', () => { + const type = createType({ + name: 'foo', + switchToModelVersionAt: '8.9.3', + }); + + expect(() => validate({ type })).toThrowErrorMatchingInlineSnapshot( + `"Type foo: can't use a patch version for switchToModelVersionAt"` + ); + }); + }); + describe('modelVersions', () => { - it('does not throw if used without migrations defined', () => { + it('throws if used without specifying switchToModelVersionAt', () => { const type = createType({ name: 'foo', modelVersions: { @@ -206,12 +236,15 @@ describe('validateTypeMigrations', () => { }, }); - expect(() => validate({ type, kibanaVersion: '3.2.3' })).not.toThrow(); + expect(() => validate({ type, kibanaVersion: '3.2.3' })).toThrowErrorMatchingInlineSnapshot( + `"Type foo: Using modelVersions requires to specify switchToModelVersionAt"` + ); }); it('throws if the version number is invalid', () => { const type = createType({ name: 'foo', + switchToModelVersionAt: '3.1.0', modelVersions: { '1.1': someModelVersion, }, @@ -225,6 +258,7 @@ describe('validateTypeMigrations', () => { it('throws when starting with a version higher than 1', () => { const type = createType({ name: 'foo', + switchToModelVersionAt: '3.1.0', modelVersions: { '2': someModelVersion, }, @@ -238,6 +272,7 @@ describe('validateTypeMigrations', () => { it('throws when there is a gap in versions', () => { const type = createType({ name: 'foo', + switchToModelVersionAt: '3.1.0', modelVersions: { '1': someModelVersion, '3': someModelVersion, @@ -263,7 +298,7 @@ describe('validateTypeMigrations', () => { describe('modelVersions with schemas', () => { const baseSchema = schema.object({ name: schema.string() }, { unknowns: 'ignore' }); - it('does not throw without specifying migrations', () => { + it('throws if used without specifying switchToModelVersionAt', () => { const type = createType({ name: 'foo', modelVersions: { @@ -282,7 +317,9 @@ describe('validateTypeMigrations', () => { }, }); - expect(() => validate({ type, kibanaVersion: '3.2.3' })).not.toThrow(); + expect(() => validate({ type, kibanaVersion: '3.2.3' })).toThrowErrorMatchingInlineSnapshot( + `"Type foo: Using modelVersions requires to specify switchToModelVersionAt"` + ); }); it('does not throw passing a model version schema map', () => { @@ -295,6 +332,7 @@ describe('validateTypeMigrations', () => { }; const type = createType({ name: 'foo', + switchToModelVersionAt: '3.1.0', modelVersions: { '1': someModelVersionWithSchema, }, @@ -312,6 +350,7 @@ describe('validateTypeMigrations', () => { const someModelVersionWithSchema = { changes: [], schemas: {} }; const type = createType({ name: 'foo', + switchToModelVersionAt: '3.1.0', modelVersions: { '1': someModelVersionWithSchema, }, @@ -325,6 +364,7 @@ describe('validateTypeMigrations', () => { it('throws when registering mapping additions not present in the global mappings', () => { const type = createType({ name: 'foo', + switchToModelVersionAt: '8.8.0', modelVersions: { '1': { changes: [ @@ -352,6 +392,7 @@ describe('validateTypeMigrations', () => { it('does not throw when registering mapping additions are present in the global mappings with a schema', () => { const type = createType({ name: 'foo', + switchToModelVersionAt: '8.8.0', modelVersions: { '1': { changes: [ @@ -390,6 +431,7 @@ describe('validateTypeMigrations', () => { it('throws when registering mapping additions different than the global mappings', () => { const type = createType({ name: 'foo', + switchToModelVersionAt: '8.8.0', modelVersions: { '1': { changes: [ @@ -419,6 +461,7 @@ describe('validateTypeMigrations', () => { const baseSchema = schema.object({ name: schema.string() }); const type = createType({ name: 'foo', + switchToModelVersionAt: '8.10.0', modelVersions: { 1: { changes: [], diff --git a/src/core/packages/saved-objects/migration-server-internal/src/document_migrator/validate_migrations.ts b/src/core/packages/saved-objects/migration-server-internal/src/document_migrator/validate_migrations.ts index 10b864d553359..0863e3907602a 100644 --- a/src/core/packages/saved-objects/migration-server-internal/src/document_migrator/validate_migrations.ts +++ b/src/core/packages/saved-objects/migration-server-internal/src/document_migrator/validate_migrations.ts @@ -15,10 +15,7 @@ import type { SavedObjectsTypeMappingDefinition, SavedObjectsModelVersionMap, } from '@kbn/core-saved-objects-server'; -import { - assertValidModelVersion, - globalSwitchToModelVersionAt, -} from '@kbn/core-saved-objects-base-server-internal'; +import { assertValidModelVersion } from '@kbn/core-saved-objects-base-server-internal'; import { SavedObjectsModelChange, SavedObjectsModelMappingsAdditionChange, @@ -36,6 +33,18 @@ export function validateTypeMigrations({ kibanaVersion: string; convertVersion?: string; }) { + if (type.switchToModelVersionAt) { + const switchToModelVersionAt = Semver.parse(type.switchToModelVersionAt); + if (!switchToModelVersionAt) { + throw new Error( + `Type ${type.name}: invalid version specified for switchToModelVersionAt: ${type.switchToModelVersionAt}` + ); + } + if (switchToModelVersionAt.patch !== 0) { + throw new Error(`Type ${type.name}: can't use a patch version for switchToModelVersionAt`); + } + } + if (type.migrations) { assertObjectOrFunction( type.migrations, @@ -53,9 +62,9 @@ export function validateTypeMigrations({ Object.entries(migrationMap).forEach(([version, migration]) => { assertValidSemver(kibanaVersion, version, type.name); assertValidTransform(migration, version, type.name); - if (Semver.gte(version, globalSwitchToModelVersionAt)) { + if (type.switchToModelVersionAt && Semver.gte(version, type.switchToModelVersionAt)) { throw new Error( - `Migration for type ${type.name} for version ${version} registered after globalSwitchToModelVersionAt (${globalSwitchToModelVersionAt})` + `Migration for type ${type.name} for version ${version} registered after switchToModelVersionAt (${type.switchToModelVersionAt})` ); } }); @@ -70,9 +79,9 @@ export function validateTypeMigrations({ Object.entries(schemaMap).forEach(([version, schema]) => { assertValidSemver(kibanaVersion, version, type.name); - if (Semver.gte(version, globalSwitchToModelVersionAt)) { + if (type.switchToModelVersionAt && Semver.gte(version, type.switchToModelVersionAt)) { throw new Error( - `Schema for type ${type.name} for version ${version} registered after globalSwitchToModelVersionAt (${globalSwitchToModelVersionAt})` + `Schema for type ${type.name} for version ${version} registered after switchToModelVersionAt (${type.switchToModelVersionAt})` ); } }); @@ -83,9 +92,9 @@ export function validateTypeMigrations({ typeof type.modelVersions === 'function' ? type.modelVersions() : type.modelVersions ?? {}; if (Object.keys(modelVersionMap).length > 0) { - if (!globalSwitchToModelVersionAt) { + if (!type.switchToModelVersionAt) { throw new Error( - `Type ${type.name}: Using modelVersions requires to specify globalSwitchToModelVersionAt` + `Type ${type.name}: Using modelVersions requires to specify switchToModelVersionAt` ); } diff --git a/src/core/packages/saved-objects/migration-server-internal/src/initial_state.test.ts b/src/core/packages/saved-objects/migration-server-internal/src/initial_state.test.ts index 7df476e9b423f..ab60da37a6b2d 100644 --- a/src/core/packages/saved-objects/migration-server-internal/src/initial_state.test.ts +++ b/src/core/packages/saved-objects/migration-server-internal/src/initial_state.test.ts @@ -82,6 +82,7 @@ describe('createInitialState', () => { changes: [], }, }, + switchToModelVersionAt: '8.10.0', }); typeRegistry.registerType({ name: 'bar', @@ -98,6 +99,7 @@ describe('createInitialState', () => { changes: [{ type: 'mappings_addition', addedMappings: {} }], }, }, + switchToModelVersionAt: '8.10.0', }); docLinks = docLinksServiceMock.createSetupContract(); logger = mockLogger.get(); diff --git a/src/core/packages/saved-objects/migration-server-internal/src/zdt/utils/build_index_mappings.test.ts b/src/core/packages/saved-objects/migration-server-internal/src/zdt/utils/build_index_mappings.test.ts index 807efc347dbbb..59d3430d6ce14 100644 --- a/src/core/packages/saved-objects/migration-server-internal/src/zdt/utils/build_index_mappings.test.ts +++ b/src/core/packages/saved-objects/migration-server-internal/src/zdt/utils/build_index_mappings.test.ts @@ -13,6 +13,7 @@ import { createType } from '../test_helpers'; const getTestTypes = () => { const foo = createType({ name: 'foo', + switchToModelVersionAt: '8.7.0', modelVersions: { 1: { changes: [] }, 2: { changes: [] }, @@ -21,6 +22,7 @@ const getTestTypes = () => { }); const bar = createType({ name: 'bar', + switchToModelVersionAt: '8.7.0', modelVersions: { 1: { changes: [] }, }, @@ -28,6 +30,7 @@ const getTestTypes = () => { }); const dolly = createType({ name: 'dolly', + switchToModelVersionAt: '8.7.0', modelVersions: () => ({ 1: { changes: [] }, 2: { changes: [] }, diff --git a/src/core/packages/saved-objects/migration-server-internal/src/zdt/utils/generate_additive_mapping_diff.test.ts b/src/core/packages/saved-objects/migration-server-internal/src/zdt/utils/generate_additive_mapping_diff.test.ts index 82ccc414eea01..125947acbcc2f 100644 --- a/src/core/packages/saved-objects/migration-server-internal/src/zdt/utils/generate_additive_mapping_diff.test.ts +++ b/src/core/packages/saved-objects/migration-server-internal/src/zdt/utils/generate_additive_mapping_diff.test.ts @@ -34,6 +34,7 @@ describe('generateAdditiveMappingDiff', () => { const getTypes = () => { const foo = createType({ name: 'foo', + switchToModelVersionAt: '8.0.0', modelVersions: { 1: stubModelVersion, 2: stubModelVersion, diff --git a/src/core/packages/saved-objects/migration-server-internal/src/zdt/utils/outdated_documents_query.test.ts b/src/core/packages/saved-objects/migration-server-internal/src/zdt/utils/outdated_documents_query.test.ts index 9156f4582a6dc..539dc9c55af85 100644 --- a/src/core/packages/saved-objects/migration-server-internal/src/zdt/utils/outdated_documents_query.test.ts +++ b/src/core/packages/saved-objects/migration-server-internal/src/zdt/utils/outdated_documents_query.test.ts @@ -21,6 +21,7 @@ describe('getOutdatedDocumentsQuery', () => { it('generates the correct query for types using model versions', () => { const fooType = createType({ name: 'foo', + switchToModelVersionAt: '8.8.0', modelVersions: { 1: dummyModelVersion, 2: dummyModelVersion, @@ -28,6 +29,7 @@ describe('getOutdatedDocumentsQuery', () => { }); const barType = createType({ name: 'bar', + switchToModelVersionAt: '8.8.0', modelVersions: { 1: dummyModelVersion, 2: dummyModelVersion, @@ -158,6 +160,7 @@ describe('getOutdatedDocumentsQuery', () => { '7.17.2': dummyMigration, '8.5.0': dummyMigration, }, + switchToModelVersionAt: '8.8.0', modelVersions: { 1: dummyModelVersion, 2: dummyModelVersion, diff --git a/src/core/packages/saved-objects/server-internal/src/apply_type_defaults.test.ts b/src/core/packages/saved-objects/server-internal/src/apply_type_defaults.test.ts new file mode 100644 index 0000000000000..f3a54dde6749d --- /dev/null +++ b/src/core/packages/saved-objects/server-internal/src/apply_type_defaults.test.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import type { SavedObjectsType } from '@kbn/core-saved-objects-server'; +import { globalSwitchToModelVersionAt } from '@kbn/core-saved-objects-base-server-internal'; +import { applyTypeDefaults } from './apply_type_defaults'; + +const createType = (parts: Partial = {}): SavedObjectsType => ({ + name: 'test', + namespaceType: 'single', + hidden: false, + mappings: { properties: {} }, + ...parts, +}); + +describe('applyTypeDefaults', () => { + describe('switchToModelVersionAt', () => { + it(`keeps the type's switchToModelVersionAt if lesser than the global version`, () => { + const type = createType({ + switchToModelVersionAt: '8.4.0', + }); + + const result = applyTypeDefaults(type); + expect(result.switchToModelVersionAt).toEqual('8.4.0'); + }); + + it(`sets switchToModelVersionAt to the global version if unspecified`, () => { + const type = createType({ + switchToModelVersionAt: undefined, + }); + + const result = applyTypeDefaults(type); + expect(result.switchToModelVersionAt).toEqual(globalSwitchToModelVersionAt); + }); + + it(`throws if switchToModelVersionAt is invalid`, () => { + const type = createType({ + switchToModelVersionAt: 'foobar', + }); + + expect(() => applyTypeDefaults(type)).toThrowErrorMatchingInlineSnapshot( + `"Type test: invalid switchToModelVersionAt provided: foobar"` + ); + }); + + it(`throws if type version is greater than the global version`, () => { + const type = createType({ + switchToModelVersionAt: '9.2.0', + }); + + expect(() => applyTypeDefaults(type)).toThrowErrorMatchingInlineSnapshot( + `"Type test: provided switchToModelVersionAt (9.2.0) is higher than maximum (8.10.0)"` + ); + }); + }); +}); diff --git a/src/core/packages/saved-objects/server-internal/src/apply_type_defaults.ts b/src/core/packages/saved-objects/server-internal/src/apply_type_defaults.ts new file mode 100644 index 0000000000000..0643179211010 --- /dev/null +++ b/src/core/packages/saved-objects/server-internal/src/apply_type_defaults.ts @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import Semver from 'semver'; +import type { SavedObjectsType } from '@kbn/core-saved-objects-server'; +import { globalSwitchToModelVersionAt } from '@kbn/core-saved-objects-base-server-internal'; + +/** + * Apply global defaults to the provided SO type. + */ +export const applyTypeDefaults = (type: SavedObjectsType): SavedObjectsType => { + let switchToModelVersionAt = type.switchToModelVersionAt; + if (switchToModelVersionAt) { + if (!Semver.valid(switchToModelVersionAt)) { + throw new Error( + `Type ${type.name}: invalid switchToModelVersionAt provided: ${switchToModelVersionAt}` + ); + } + if (Semver.gt(switchToModelVersionAt, globalSwitchToModelVersionAt)) { + throw new Error( + `Type ${type.name}: provided switchToModelVersionAt (${switchToModelVersionAt}) is higher than maximum (${globalSwitchToModelVersionAt})` + ); + } + } else { + switchToModelVersionAt = globalSwitchToModelVersionAt; + } + + return { + ...type, + switchToModelVersionAt, + }; +}; diff --git a/src/core/packages/saved-objects/server-internal/src/saved_objects_service.test.mocks.ts b/src/core/packages/saved-objects/server-internal/src/saved_objects_service.test.mocks.ts index d40a09daa580e..ebd4f541b063a 100644 --- a/src/core/packages/saved-objects/server-internal/src/saved_objects_service.test.mocks.ts +++ b/src/core/packages/saved-objects/server-internal/src/saved_objects_service.test.mocks.ts @@ -51,3 +51,12 @@ export const registerRoutesMock = jest.fn(); jest.doMock('./routes', () => ({ registerRoutes: registerRoutesMock, })); + +export const applyTypeDefaultsMock = jest.fn(); +jest.doMock('./apply_type_defaults', () => { + const actual = jest.requireActual('./apply_type_defaults'); + return { + ...actual, + applyTypeDefaults: applyTypeDefaultsMock, + }; +}); diff --git a/src/core/packages/saved-objects/server-internal/src/saved_objects_service.test.ts b/src/core/packages/saved-objects/server-internal/src/saved_objects_service.test.ts index 0c9aab0a2b3fc..70e8fcf17c797 100644 --- a/src/core/packages/saved-objects/server-internal/src/saved_objects_service.test.ts +++ b/src/core/packages/saved-objects/server-internal/src/saved_objects_service.test.ts @@ -17,6 +17,7 @@ import { migratorInstanceMock, registerRoutesMock, typeRegistryInstanceMock, + applyTypeDefaultsMock, } from './saved_objects_service.test.mocks'; import { BehaviorSubject, firstValueFrom, EMPTY } from 'rxjs'; import { skip } from 'rxjs'; @@ -70,6 +71,7 @@ describe('SavedObjectsService', () => { beforeEach(() => { deprecationsSetup = createDeprecationRegistryProviderMock(); + applyTypeDefaultsMock.mockReset().mockImplementation((type: unknown) => type); }); const createCoreContext = ({ @@ -344,21 +346,50 @@ describe('SavedObjectsService', () => { }); describe('#registerType', () => { - it('registers the type to the internal typeRegistry', async () => { + it('calls `applyTypeDefaults` with the correct parameters', async () => { // we mocked registerCoreObjectTypes above, so this test case only reflects direct calls to the registerType method const coreContext = createCoreContext(); const soService = new SavedObjectsService(coreContext); const setup = await soService.setup(createSetupDeps()); - const type = { + const inputType = { name: 'someType', hidden: false, namespaceType: 'single' as 'single', mappings: { properties: {} }, }; - setup.registerType(type); + + applyTypeDefaultsMock.mockReturnValue(inputType); + + setup.registerType(inputType); + + expect(applyTypeDefaultsMock).toHaveBeenCalledTimes(1); + expect(applyTypeDefaultsMock).toHaveBeenCalledWith(inputType); + }); + + it('registers the type returned by `applyTypeDefaults` to the internal typeRegistry', async () => { + // we mocked registerCoreObjectTypes above, so this test case only reflects direct calls to the registerType method + const coreContext = createCoreContext(); + const soService = new SavedObjectsService(coreContext); + const setup = await soService.setup(createSetupDeps()); + + const inputType = { + name: 'someType', + hidden: false, + namespaceType: 'single' as 'single', + mappings: { properties: {} }, + }; + const returnedType = { + ...inputType, + switchToModelVersionAt: '9.9.9', + }; + + applyTypeDefaultsMock.mockReturnValue(returnedType); + + setup.registerType(inputType); + expect(typeRegistryInstanceMock.registerType).toHaveBeenCalledTimes(1); - expect(typeRegistryInstanceMock.registerType).toHaveBeenCalledWith(type); + expect(typeRegistryInstanceMock.registerType).toHaveBeenCalledWith(returnedType); }); }); diff --git a/src/core/packages/saved-objects/server-internal/src/saved_objects_service.ts b/src/core/packages/saved-objects/server-internal/src/saved_objects_service.ts index eb64e142721c3..04be2f5929f0b 100644 --- a/src/core/packages/saved-objects/server-internal/src/saved_objects_service.ts +++ b/src/core/packages/saved-objects/server-internal/src/saved_objects_service.ts @@ -64,6 +64,7 @@ import { registerRoutes } from './routes'; import { calculateStatus$ } from './status'; import { registerCoreObjectTypes } from './object_types'; import { getSavedObjectsDeprecationsProvider } from './deprecations'; +import { applyTypeDefaults } from './apply_type_defaults'; import { getAllIndices } from './utils'; import { MIGRATION_CLIENT_OPTIONS } from './constants'; @@ -218,7 +219,7 @@ export class SavedObjectsService if (this.started) { throw new Error('cannot call `registerType` after service startup.'); } - this.typeRegistry.registerType(type); + this.typeRegistry.registerType(applyTypeDefaults(type)); }, getTypeRegistry: () => this.typeRegistry, getDefaultIndex: () => MAIN_SAVED_OBJECT_INDEX, diff --git a/src/core/packages/saved-objects/server/docs/model_versions.md b/src/core/packages/saved-objects/server/docs/model_versions.md index 83796ac658ee6..f3d67d6d299de 100644 --- a/src/core/packages/saved-objects/server/docs/model_versions.md +++ b/src/core/packages/saved-objects/server/docs/model_versions.md @@ -100,6 +100,7 @@ That way: ```ts const myType: SavedObjectsType = { name: 'test', + switchToModelVersionAt: '8.10.0', modelVersions: { 1: modelVersion1, // valid: start with version 1 2: modelVersion2, // valid: no gap between versions @@ -112,6 +113,7 @@ const myType: SavedObjectsType = { ```ts const myType: SavedObjectsType = { name: 'test', + switchToModelVersionAt: '8.10.0', modelVersions: { 2: modelVersion2, // invalid: first version must be 1 4: modelVersion3, // invalid: skipped version 3 @@ -130,6 +132,7 @@ are not just functions as the previous migrations were, but structured objects d ```ts const myType: SavedObjectsType = { name: 'test', + switchToModelVersionAt: '8.10.0', modelVersions: { 1: { changes: [ @@ -370,6 +373,7 @@ The definition of the type at version 1 would look like: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { // initial (and current) model version 1: { @@ -427,6 +431,7 @@ The full type definition after the addition of the new model version: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { 1: { changes: [], @@ -518,6 +523,7 @@ the full type definition after the addition of the model version 2 would be: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { 1: { changes: [ @@ -613,6 +619,7 @@ The full type definition would look like: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { 1: { changes: [ @@ -682,6 +689,7 @@ The definition of the type at version 1 would look like: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { // initial (and current) model version 1: { @@ -755,6 +763,7 @@ The full type definition after the addition of the new model version: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { // initial (and current) model version 1: { @@ -822,6 +831,7 @@ The full type definition after the data removal would look like: const myType: SavedObjectsType = { name: 'test', namespaceType: 'single', + switchToModelVersionAt: '8.10.0', modelVersions: { // initial (and current) model version 1: { diff --git a/src/core/packages/saved-objects/server/src/saved_objects_type.ts b/src/core/packages/saved-objects/server/src/saved_objects_type.ts index 3a01fc205a47c..3f009ce5943f9 100644 --- a/src/core/packages/saved-objects/server/src/saved_objects_type.ts +++ b/src/core/packages/saved-objects/server/src/saved_objects_type.ts @@ -190,6 +190,60 @@ export interface SavedObjectsType { * ``` */ modelVersions?: SavedObjectsModelVersionMap | SavedObjectsModelVersionMapProvider; + + /** + * Allows to opt-in to the model version API. + * + * Must be a valid semver version (with the patch version being necessarily 0) + * + * When specified, the type will switch from using the {@link SavedObjectsType.migrations | legacy migration API} + * to use the {@link SavedObjectsType.modelVersions | modelVersion API} after the specified version. + * + * Once opted in, it will no longer be possible to use the legacy migration API after the specified version. + * + * @example A **valid** usage example would be: + * + * ```ts + * { + * name: 'foo', + * // other mandatory attributes... + * switchToModelVersionAt: '8.8.0', + * migrations: { + * '8.1.0': migrateTo810, + * '8.7.0': migrateTo870, + * }, + * modelVersions: { + * '1': modelVersion1 + * } + * } + * ``` + * + * @example An **invalid** usage example would be: + * + * ```ts + * { + * name: 'foo', + * // other mandatory attributes... + * switchToModelVersionAt: '8.9.0', + * migrations: { + * '8.1.0': migrateTo8_1, + * '8.9.0': migrateTo8_9, // error: migration registered for the switch version + * '8.10.0': migrateTo8_10, // error: migration registered for after the switch version + * }, + * modelVersions: { + * '1': modelVersion1 + * } + * } + * ``` + * + * Please refer to the {@link SavedObjectsType.modelVersions | modelVersion API} for more documentation on + * the new API. + * + * @remarks All types will be forced to switch to use the new API during `8.10.0`. This switch is + * allowing types owners to switch their types before the milestone (and for testing purposes). + */ + switchToModelVersionAt?: string; + /** * Function returning the title to display in the management table. * If not defined, will use the object's type and id to generate a label. diff --git a/src/core/packages/test-helpers/so-type-serializer/src/extract_migration_info.test.ts b/src/core/packages/test-helpers/so-type-serializer/src/extract_migration_info.test.ts index f7bfa713dc4e0..207c50dad4658 100644 --- a/src/core/packages/test-helpers/so-type-serializer/src/extract_migration_info.test.ts +++ b/src/core/packages/test-helpers/so-type-serializer/src/extract_migration_info.test.ts @@ -161,6 +161,15 @@ describe('extractMigrationInfo', () => { }); describe('modelVersions', () => { + it('returns the correct switchToModelVersionAt', () => { + const type = createType({ + switchToModelVersionAt: '8.8.0', + }); + const output = extractMigrationInfo(type); + + expect(output.switchToModelVersionAt).toEqual('8.8.0'); + }); + it('returns a proper summary of the model versions', () => { const type = createType({ modelVersions: { @@ -310,6 +319,7 @@ describe('extractMigrationInfo', () => { it('returns the correct values for schemas', () => { const type = createType({ + switchToModelVersionAt: '8.8.0', modelVersions: { 1: { changes: [], @@ -364,6 +374,7 @@ describe('extractMigrationInfo', () => { ], }, }, + switchToModelVersionAt: '8.8.0', }); const output = extractMigrationInfo(type); @@ -371,6 +382,7 @@ describe('extractMigrationInfo', () => { expect(output).toEqual( expect.objectContaining({ migrationVersions: ['7.17.7', '8.0.2', '8.3.3'], + switchToModelVersionAt: '8.8.0', modelVersions: [ { version: '1', diff --git a/src/core/packages/test-helpers/so-type-serializer/src/extract_migration_info.ts b/src/core/packages/test-helpers/so-type-serializer/src/extract_migration_info.ts index 9fcc90e11ff19..41da158916144 100644 --- a/src/core/packages/test-helpers/so-type-serializer/src/extract_migration_info.ts +++ b/src/core/packages/test-helpers/so-type-serializer/src/extract_migration_info.ts @@ -80,6 +80,7 @@ export const extractMigrationInfo = (soType: SavedObjectsType): SavedObjectTypeM mappings: getFlattenedObject(soType.mappings ?? {}), hasExcludeOnUpgrade: !!soType.excludeOnUpgrade, modelVersions, + switchToModelVersionAt: soType.switchToModelVersionAt, }; }; diff --git a/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts b/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts index 0a15e2497216d..6a3ae074b918f 100644 --- a/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts +++ b/src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts @@ -59,136 +59,136 @@ describe('checking migration metadata changes on all registered SO types', () => expect(hashMap).toMatchInlineSnapshot(` Object { - "action": "696d997e420024a8cf973da94d905c8756e1177c", - "action_task_params": "cd91a48515202852ebf1fed0d999cd96f6b2823e", - "ad_hoc_run_params": "690b8991f48c73a04e6a8cf41fd4967a42f8e552", - "alert": "581f322afd6784aebdb80f872b825a928533d364", - "api_key_pending_invalidation": "cef0693ec88475a0e1f43614cfa6ca43c24d0338", - "apm-custom-dashboards": "9b08d5d5222131c6981a70144b1d61648757a613", - "apm-indices": "b844821e9675768b1cb78f6d91ff336ed09d4739", - "apm-server-schema": "6ee813dd2407b061b4eeda92c5f695d3bf9827df", - "apm-service-group": "3843d13e18dd2071d68de0cec9787eb0f83f6af5", - "apm-telemetry": "9c02ac4e9778422cb7f66a4d6b62f672df4644cc", - "app_search_telemetry": "9269643c9a5894998b44883f7f7d07a453fd6a95", - "application_usage_daily": "9867f6e1355124f822beab051e0fbac4cc117eac", - "application_usage_totals": "9469a48ab887761a73ee3719b8d401ac627f1eb1", - "background-task-node": "1c7a5767b34d1b5672758b604296f662bde68d0a", - "canvas-element": "288fd8d216eb49cbeb5e8f7491f207ef074b80dd", - "canvas-workpad": "5cd605383a100a27941cca6cbf2d954aa96a16e2", - "canvas-workpad-template": "f9a6ffab76ddfcd8fa3823002aa576c8f1d0e686", - "cases": "193f4d0f5e9f1e3f62852eab15add6220bdf2b0c", - "cases-comments": "9e336aceb6a330452d1cbf0ba1b8fd542c9e3856", - "cases-configure": "66d4c64d83b464f5166005b8ffa03b721fcaaf8b", - "cases-connector-mappings": "877bb4d52e9821e330622bd75fba799490ec6952", - "cases-rules": "24c69413a726f1b4c37c000acc4216ff046af59f", - "cases-telemetry": "fdeddcef28c75d8c66422475a829e75d37f0b668", - "cases-user-actions": "8ad74294b71edffa58fad7a40eea2388209477c9", - "cloud": "783f93b25887278becdf83841addd4e726550a51", - "cloud-security-posture-settings": "20453bee65db286a2cc1994e65cf4d7297d8173e", - "config": "7cb03ac2211a1a8a17a622632b6e6858e758aabb", - "config-global": "d9791e8f73edee884630e1cb6e4954ae513ce75e", - "connector_token": "e25821ecec3061806a6a9d4953273c18a749cc0f", + "action": "0e6fc0b74c7312a8c11ff6b14437b93a997358b8", + "action_task_params": "2e475d8b62e2de50b77f58cda309efb537e1d543", + "ad_hoc_run_params": "c7419760e878207231c3c8a25ec4d78360e07bf7", + "alert": "fcdf16a71b7209fee12caafdbe6664f8ed494cc2", + "api_key_pending_invalidation": "8f5554d1984854011b8392d9a6f7ef985bcac03c", + "apm-custom-dashboards": "b67128f78160c288bd7efe25b2da6e2afd5e82fc", + "apm-indices": "8a2d68d415a4b542b26b0d292034a28ffac6fed4", + "apm-server-schema": "58a8c6468edae3d1dc520f0134f59cf3f4fd7eff", + "apm-service-group": "66dfc1ddd40bad8f693c873bf6002ca30079a4ae", + "apm-telemetry": "4df255b8b022f5d160687db736b9abcd6ab173fe", + "app_search_telemetry": "36234f19573ad397ac30197c45ac219921cc3106", + "application_usage_daily": "20142d23fe5d05ba22b4bc46614d99883bc488f0", + "application_usage_totals": "a29ab014edc20382b9ce22ede221b18cee5d93a6", + "background-task-node": "e61f0ea9923fa05b3af0aae6c6baf2f0283e14b3", + "canvas-element": "cdedc2123eb8a1506b87a56b0bcce60f4ec08bc8", + "canvas-workpad": "9d82aafb19586b119e5c9382f938abe28c26ca5c", + "canvas-workpad-template": "c077b0087346776bb3542b51e1385d172cb24179", + "cases": "91771732e2e488e4c1b1ac468057925d1c6b32b5", + "cases-comments": "5cb0a421588831c2a950e50f486048b8aabbae25", + "cases-configure": "44ed7b8e0f44df39516b8870589b89e32224d2bf", + "cases-connector-mappings": "f9d1ac57e484e69506c36a8051e4d61f4a8cfd25", + "cases-rules": "6d1776f5c46a99e1a0f3085c537146c1cdfbc829", + "cases-telemetry": "f219eb7e26772884342487fc9602cfea07b3cedc", + "cases-user-actions": "483f10db9b3bd1617948d7032a98b7791bf87414", + "cloud": "b549f4f7ab1fd41aab366a66afa52a2a008aefea", + "cloud-security-posture-settings": "e0f61c68bbb5e4cfa46ce8994fa001e417df51ca", + "config": "0ff10ca7b058b5775556688280b48347cb18e281", + "config-global": "8e8a134a2952df700d7d4ec51abb794bbd4cf6da", + "connector_token": "79977ea2cb1530ba7e315b95c1b5a524b622a6b3", "core-usage-stats": "b3c04da317c957741ebcdedfea4524049fdc79ff", - "csp-rule-template": "0cc86d4eb9f4eaf0e9ceab42a4c18a9ff9a43526", - "dashboard": "6b768591e1fe390b9a358db017cb26cb2357807f", - "dynamic-config-overrides": "ac104a1a4498f8d2e477681d9fb43449b4c56afa", - "endpoint:unified-user-artifact-manifest": "4237f2cc2dbbc28504c70f1c2965b5f23710f9cb", - "endpoint:user-artifact-manifest": "8ad9bd235dcfdc18b567aef0dc36ac686193dc89", - "enterprise_search_telemetry": "4b41830e3b28a16eb92dee0736b44ae6276ced9b", - "entity-definition": "02ea6a34291d939262c45f4f81da01249ba13753", - "entity-discovery-api-key": "094f1eae0e069e5f8bf2523db1a14072a8e29271", - "entity-engine-status": "49fb6dc6d70a935572faf4593800477beeccd120", - "epm-packages": "1e236a1656734cc16f45946a48bfed2134799f7d", - "epm-packages-assets": "00c8b5e5bf059627ffc9fbde920e1ac75926c5f6", - "event-annotation-group": "c67d5863d7cac02d800c543724ef29b66d12e77e", - "event_loop_delays_daily": "ef49e7f15649b551b458c7ea170f3ed17f89abd0", - "exception-list": "38181294f64fc406c15f20d85ca306c8a4feb3c0", - "exception-list-agnostic": "d527ce9d12b134cb163150057b87529043a8ec77", - "favorites": "a4db4c97692e8468c96abac1cbd2b9d57150f173", - "file": "487a562dd895407307980cc4404ca08e87e8999d", - "file-upload-usage-collection-telemetry": "c6fcb9a7efcf19b2bb66ca6e005bfee8961f6073", - "fileShare": "f07d346acbb724eacf139a0fb781c38dc5280115", - "fleet-agent-policies": "a977f4de060fc15e49148e4c26680d1dee5c5205", - "fleet-fleet-server-host": "795c0e79438a260bd860419454bcc432476d4396", - "fleet-message-signing-keys": "0c6da6a680807e568540b2aa263ae52331ba66db", - "fleet-package-policies": "be03d7cf73c3757a1bf65cbf77a5a4ff809ae682", - "fleet-preconfiguration-deletion-record": "3afad160748b430427086985a3445fd8697566d5", - "fleet-proxy": "94d0a902a0fd22578d7d3a20873b95d902e25245", - "fleet-setup-lock": "ce9a2dcfb2e6f7260d129636a26c9ca98b13e464", - "fleet-space-settings": "b8f60506cf5fea1429ad84dfb8644cf261fd7427", - "fleet-uninstall-tokens": "216be68d8426052f9e7529e2e0569b7950676537", - "graph-workspace": "565642a208fe7413b487aea979b5b153e4e74abe", - "guided-onboarding-guide-state": "3257825ae840309cb676d64b347107db7b76f30a", - "guided-onboarding-plugin-state": "2d3ef3069ca8e981cafe8647c0c4a4c20739db10", - "index-pattern": "cd51191712081278c2af83d16552c3438ef83353", - "infra-custom-dashboards": "20231f5c1a13633c8c85f4e1257fa0c6156f6714", - "infrastructure-monitoring-log-view": "8040108f02ef27419cff79077384379709d44bbc", - "infrastructure-ui-source": "2311f7d0abe2a713aa71e30ee24f78828d4acfc1", - "ingest-agent-policies": "11945ce3f87ad242d6fc89509c4318dae74008cc", - "ingest-download-sources": "e6b6c76a67a1882c861177ee9e8ff2c607b7eeea", - "ingest-outputs": "f92200366d6b9f142a81f094154e17987910c535", - "ingest-package-policies": "c12bdd0a3d35255265d501e3ab0e266579b5fbbf", - "ingest_manager_settings": "164096e0a8957ad8e7a298372c27035e73bf3bb6", - "inventory-view": "e125c6e6e49729055421e7b3a0544f24330d8dc6", - "kql-telemetry": "92d6357aa3ce28727492f86a54783f802dc38893", + "csp-rule-template": "c151324d5f85178169395eecb12bac6b96064654", + "dashboard": "211e9ca30f5a95d5f3c27b1bf2b58e6cfa0c9ae9", + "dynamic-config-overrides": "eb3ec7d96a42991068eda5421eecba9349c82d2b", + "endpoint:unified-user-artifact-manifest": "71c7fcb52c658b21ea2800a6b6a76972ae1c776e", + "endpoint:user-artifact-manifest": "1c3533161811a58772e30cdc77bac4631da3ef2b", + "enterprise_search_telemetry": "9ac912e1417fc8681e0cd383775382117c9e3d3d", + "entity-definition": "1c6bff35c423d5dc5650bc806cf2899e4706a0bc", + "entity-discovery-api-key": "c267a65c69171d1804362155c1378365f5acef88", + "entity-engine-status": "09f6a617020708e4f638137e5ef35bd9534133be", + "epm-packages": "5a9f55e38d424f5b5ebbfeac802788b5b05d867f", + "epm-packages-assets": "7a3e58efd9a14191d0d1a00b8aaed30a145fd0b1", + "event-annotation-group": "715ba867d8c68f3c9438052210ea1c30a9362582", + "event_loop_delays_daily": "01b967e8e043801357503de09199dfa3853bab88", + "exception-list": "4aebc4e61fb5d608cae48eaeb0977e8db21c61a4", + "exception-list-agnostic": "6d3262d58eee28ac381ec9654f93126a58be6f5d", + "favorites": "e9773d802932ea85547b120e0efdd9a4f11ff4c6", + "file": "6b65ae5899b60ebe08656fd163ea532e557d3c98", + "file-upload-usage-collection-telemetry": "06e0a8c04f991e744e09d03ab2bd7f86b2088200", + "fileShare": "5be52de1747d249a221b5241af2838264e19aaa1", + "fleet-agent-policies": "f69f7c5639f4cf9e85077c904e161f3574ac3ca2", + "fleet-fleet-server-host": "232d98738d5321b86edc426e21a9ca2f607da999", + "fleet-message-signing-keys": "93421f43fed2526b59092a4e3c65d64bc2266c0f", + "fleet-package-policies": "b1ded996118af658bc420a737ff3c4d784641fc7", + "fleet-preconfiguration-deletion-record": "c52ea1e13c919afe8a5e8e3adbb7080980ecc08e", + "fleet-proxy": "6cb688f0d2dd856400c1dbc998b28704ff70363d", + "fleet-setup-lock": "0dc784792c79b5af5a6e6b5dcac06b0dbaa90bde", + "fleet-space-settings": "b278e82a33978900e53a1253884b5bdbd929c9bb", + "fleet-uninstall-tokens": "371a691206845b364bcf6d3693ca7905ffdb71a4", + "graph-workspace": "5cc6bb1455b078fd848c37324672163f09b5e376", + "guided-onboarding-guide-state": "d338972ed887ac480c09a1a7fbf582d6a3827c91", + "guided-onboarding-plugin-state": "bc109e5ef46ca594fdc179eda15f3095ca0a37a4", + "index-pattern": "997108a9ea1e8076e22231e1c95517cdb192b9c5", + "infra-custom-dashboards": "1a5994f2e05bb8a1609825ddbf5012f77c5c67f3", + "infrastructure-monitoring-log-view": "5f86709d3c27aed7a8379153b08ee5d3d90d77f5", + "infrastructure-ui-source": "113182d6895764378dfe7fa9fa027244f3a457c4", + "ingest-agent-policies": "cfe66f4aeca8f53b26bd4ddb0e956de1637d774e", + "ingest-download-sources": "5be99940d6b5f9121b2fd279708d14e2bc0bde26", + "ingest-outputs": "6743521f501bd77b1523dbb1df48d7c47fdad529", + "ingest-package-policies": "6a80000fdf2544f2485b0c6a51ecc434b6a12987", + "ingest_manager_settings": "111a616eb72627c002029c19feb9e6c439a10505", + "inventory-view": "fd2b7fe713956f261018dded00d8f8c986417763", + "kql-telemetry": "93c1d16c1a0dfca9c8842062cf5ef8f62ae401ad", "legacy-url-alias": "9b8cca3fbb2da46fd12823d3cd38fdf1c9f24bc8", - "lens": "6fa6bdc5de12859815de6e50488fa2a7b038278a", - "lens-ui-telemetry": "d6c4e330d170eefc6214dbf77a53de913fa3eebc", - "links": "53ae5a770d69eee34d842617be761cd059ab4b51", - "maintenance-window": "f3f19d1828e91418d13703ce6009e9c76a1686f9", - "map": "7902b2e2a550e0b73fd5aa6c4e2ba3a4e6558877", - "metrics-data-source": "6525efc71b46a85f12a13953c4be15a9eb316723", - "metrics-explorer-view": "713dbf1ab5e067791d19170f715eb82cf07ebbcc", - "ml-job": "12e21f1b1adfcc1052dc0b10c7459de875653b94", - "ml-module": "7747963b9646733cb1996f13fb64f5cf046e65d9", - "ml-trained-model": "49a1685d79990ad05ea1d1d30e28456fe002f3b9", - "monitoring-telemetry": "24f7393dfacb6c7b0f7ad7d242171a1c29feaa48", - "observability-onboarding-state": "1ac5d69f51382ecbc999b2922754baabc1316fba", - "osquery-manager-usage-metric": "23a8f08a98dd0f58ab4e559daa35b06edc40ed4f", - "osquery-pack": "784df8f1045e38a3fff4b77ce9aa729bfc0c3058", - "osquery-pack-asset": "42d5503cd17e1a08e7d822843934f3c92972e246", - "osquery-saved-query": "a8ef11610473e3d1b51a8fdacb2799d8a610818e", - "policy-settings-protection-updates-note": "c05c4c33a5e5bd1fa153991f300d040ac5d6f38d", - "privilege-monitoring-status": "4daec76df427409bcd64250f5c23f5ab86c8bac3", - "product-doc-install-status": "ee7817c45bf1c41830290c8ef535e726c86f7c19", - "query": "1966ccce8e9853018111fb8a1dee500228731d9e", - "risk-engine-configuration": "533a0a3f2dbef1c95129146ec4d5714de305be1a", - "rules-settings": "53f94e5ce61f5e75d55ab8adbc1fb3d0937d2e0b", - "sample-data-telemetry": "c38daf1a49ed24f2a4fb091e6e1e833fccf19935", - "search": "33a40cd7fc42cbeabe8e4237fc8377727ae375f7", - "search-session": "fae0dfc63274d6a3b90ca583802c48cab8760637", - "search-telemetry": "1bbaf2db531b97fa04399440fa52d46e86d54dd8", - "search_playground": "3eba7e7c4563f03f76aea02f5dd3a7a739bf51a3", - "security-ai-prompt": "1fc1c56cc078ed2c5506bb5a4e09f6876d02c97c", - "security-rule": "151108f4906744a137ddc89f5988310c5b9ba8b6", - "security-solution-signals-migration": "0be3bed0f2ff4fe460493751b8be610a785c5c98", - "siem-detection-engine-rule-actions": "123c130dc38120a470d8db9fed9a4cebd2046445", - "siem-ui-timeline": "9906092f527a21abdfab10e43c86b228ebc3861b", - "siem-ui-timeline-note": "13c9d4c142f96624a93a623c6d7cba7e1ae9b5a6", - "siem-ui-timeline-pinned-event": "96a43d59b9e2fc11f12255a0cb47ef0a3d83af4c", - "slo": "79878844eda6ac3d858c19255d9714752b1bb081", - "slo-settings": "9a74f29769cb973a726852fcb1129481b45ce577", - "space": "758dd69293d1cd5a0190753cfd93101fe7693604", - "spaces-usage-stats": "084bd0f080f94fb5735d7f3cf12f13ec92f36bad", - "synthetics-dynamic-settings": "7804b079cc502f16526f7c9491d1397cc1ec67db", - "synthetics-monitor": "ed46c9bfc58fba359c9a9538a871a03a53cc6454", - "synthetics-param": "9776c9b571d35f0d0397e8915e035ea1dc026db7", - "synthetics-private-location": "27aaa44f792f70b734905e44e3e9b56bbeac7b86", - "synthetics-privates-locations": "36036b881524108c7327fe14bd224c6e4d972cb5", - "tag": "87f21f07df9cc37001b15a26e413c18f50d1fbfe", - "task": "4bd8e19960b83c88f3cdf766ace268c081a1c619", - "telemetry": "3b3b89cf411a2a2e60487cef6ccdbc5df691aeb9", - "threshold-explorer-view": "5e2388a6835cec3c68c98b450cd267d66cce925f", - "ui-metric": "410a8ad28e0f44b161c960ff0ce950c712b17c52", - "upgrade-assistant-ml-upgrade-operation": "d8816e5ce32649e7a3a43e2c406c632319ff84bb", - "upgrade-assistant-reindex-operation": "09ac8ed9c9acf7e8ece8eafe47d7019ea1472144", - "uptime-dynamic-settings": "001c1cc76876af3012445b1ba2adb60cae9c9180", - "uptime-synthetics-api-key": "599319bedbfa287e8761e1ba49d536417a33fa13", - "url": "816fa15bfe460ce39108ed8095e60fdbfcc40f11", - "usage-counter": "1fba2f21e9ec360324a96bab3760c1055c78d1c1", - "usage-counters": "f478b2668be350f5bdc08d9e1cf6fbce0e079f61", - "visualization": "cee4d02c56af349054642c6744bf9c471c1ad941", - "workplace_search_telemetry": "10e278fe9ae1396bfc36ae574bc387d7e696d43f", + "lens": "5cfa2c52b979b4f8df56dd13c477e152183468b9", + "lens-ui-telemetry": "8c47a9e393861f76e268345ecbadfc8a5fb1e0bd", + "links": "1dd432cc94619a513b75cec43660a50be7aadc90", + "maintenance-window": "b84d9e0b3f89be0ae4b6fe1af6e38b4cd2554931", + "map": "76c71023bd198fb6b1163b31bafd926fe2ceb9da", + "metrics-data-source": "81b69dc9830699d9ead5ac8dcb9264612e2a3c89", + "metrics-explorer-view": "98cf395d0e87b89ab63f173eae16735584a8ff42", + "ml-job": "150e1ab260e87f9963cc99e013304b9c54703dab", + "ml-module": "94f210e60504fe0cc8241d867af97f8130250359", + "ml-trained-model": "482195cefd6b04920e539d34d7356d22cb68e4f3", + "monitoring-telemetry": "5d91bf75787d9d4dd2fae954d0b3f76d33d2e559", + "observability-onboarding-state": "34eef666124a9e4ad1c607d0097cc25128764681", + "osquery-manager-usage-metric": "983bcbc3b7dda0aad29b20907db233abba709bcc", + "osquery-pack": "702e86b1a936153b39f65b0781bdc136e186e123", + "osquery-pack-asset": "cd140bc2e4b092e93692b587bf6e38051ef94c75", + "osquery-saved-query": "6095e288750aa3164dfe186c74bc5195c2bf2bd4", + "policy-settings-protection-updates-note": "33924bb246f9e5bcb876109cc83e3c7a28308352", + "privilege-monitoring-status": "9b11c4a49e679e2827b0468ba27269a19345c049", + "product-doc-install-status": "ca6e96840228e4cc2f11bae24a0797f4f7238c8c", + "query": "501bece68f26fe561286a488eabb1a8ab12f1137", + "risk-engine-configuration": "bab237d09c2e7189dddddcb1b28f19af69755efb", + "rules-settings": "ba57ef1881b3dcbf48fbfb28902d8f74442190b2", + "sample-data-telemetry": "37441b12f5b0159c2d6d5138a494c9f440e950b5", + "search": "0aa6eefb37edd3145be340a8b67779c2ca578b22", + "search-session": "b2fcd840e12a45039ada50b1355faeafa39876d1", + "search-telemetry": "b568601618744720b5662946d3103e3fb75fe8ee", + "search_playground": "9e06ddbaad7c9eeb24b24c871b6b3df484d6c1ed", + "security-ai-prompt": "cc8ee5aaa9d001e89c131bbd5af6bc80bc271046", + "security-rule": "07abb4d7e707d91675ec0495c73816394c7b521f", + "security-solution-signals-migration": "9d99715fe5246f19de2273ba77debd2446c36bb1", + "siem-detection-engine-rule-actions": "54f08e23887b20da7c805fab7c60bc67c428aff9", + "siem-ui-timeline": "d3de8ff3617be8f2a799d66b1471b9be6124bf40", + "siem-ui-timeline-note": "0a32fb776907f596bedca292b8c646496ae9c57b", + "siem-ui-timeline-pinned-event": "082daa3ce647b33873f6abccf340bdfa32057c8d", + "slo": "9a9995e4572de1839651c43b5fc4dc8276bb5815", + "slo-settings": "f6b5ed339470a6a2cda272bde1750adcf504a11b", + "space": "953a72d8962d829e7ea465849297c5e44d8e9a2d", + "spaces-usage-stats": "3abca98713c52af8b30300e386c7779b3025a20e", + "synthetics-dynamic-settings": "4b40a93eb3e222619bf4e7fe34a9b9e7ab91a0a7", + "synthetics-monitor": "5ceb25b6249bd26902c9b34273c71c3dce06dbea", + "synthetics-param": "3ebb744e5571de678b1312d5c418c8188002cf5e", + "synthetics-private-location": "8cecc9e4f39637d2f8244eb7985c0690ceab24be", + "synthetics-privates-locations": "f53d799d5c9bc8454aaa32c6abc99a899b025d5c", + "tag": "e2544392fe6563e215bb677abc8b01c2601ef2dc", + "task": "fd81cc235a5c7f64e9487e47f1ef73b3b6bfbe98", + "telemetry": "7b00bcf1c7b4f6db1192bb7405a6a63e78b699fd", + "threshold-explorer-view": "175306806f9fc8e13fcc1c8953ec4ba89bda1b70", + "ui-metric": "d227284528fd19904e9d972aea0a13716fc5fe24", + "upgrade-assistant-ml-upgrade-operation": "421f52731cb24e242d70672ba4725e169277efb3", + "upgrade-assistant-reindex-operation": "01f3c3e051659ace56492a73928987e717537a93", + "uptime-dynamic-settings": "b6756ff71d6b5258971b1c8fd433d167affbde52", + "uptime-synthetics-api-key": "7ae976a461248f9dbd8442af14a179bdbc229eca", + "url": "c923a4a5002a09c0080c9095e958f07d518e6704", + "usage-counter": "1690e9b642393c467e560fd14dd317dea24a14ee", + "usage-counters": "48782b3bcb6b5a23ba6f2bfe3a380d835e68890a", + "visualization": "93a3e73994ad836fe2b1dccbe208238f41f63da0", + "workplace_search_telemetry": "52b32b47ee576f554ac77cb1d5896dfbcfe9a1fb", } `); expect(Object.keys(hashMap).length).toEqual(SAVED_OBJECT_TYPES_COUNT); diff --git a/src/core/server/integration_tests/saved_objects/migrations/fixtures/zdt_base.fixtures.ts b/src/core/server/integration_tests/saved_objects/migrations/fixtures/zdt_base.fixtures.ts index 193b41083d215..019e2755290c3 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/fixtures/zdt_base.fixtures.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/fixtures/zdt_base.fixtures.ts @@ -53,6 +53,7 @@ export const getFooType = () => { someField: { type: 'text' }, }, }, + switchToModelVersionAt: '8.7.0', modelVersions: { '1': dummyModelVersion, '2': dummyModelVersion, @@ -68,6 +69,7 @@ export const getBarType = () => { aKeyword: { type: 'keyword' }, }, }, + switchToModelVersionAt: '8.7.0', modelVersions: { '1': dummyModelVersion, }, @@ -83,6 +85,7 @@ export const getSampleAType = () => { boolean: { type: 'boolean' }, }, }, + switchToModelVersionAt: '8.7.0', modelVersions: { '1': dummyModelVersion, }, @@ -98,6 +101,7 @@ export const getSampleBType = () => { text2: { type: 'text' }, }, }, + switchToModelVersionAt: '8.7.0', modelVersions: { '1': dummyModelVersion, }, @@ -113,6 +117,7 @@ export const getDeletedType = () => { text: { type: 'text' }, }, }, + switchToModelVersionAt: '8.7.0', modelVersions: { '1': dummyModelVersion, }, @@ -128,6 +133,7 @@ export const getExcludedType = () => { value: { type: 'integer' }, }, }, + switchToModelVersionAt: '8.7.0', modelVersions: { '1': dummyModelVersion, }, diff --git a/src/core/server/integration_tests/saved_objects/migrations/group4/v2_md5_to_mv.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group4/v2_md5_to_mv.test.ts index cd0e84067dfa6..a9bb6716073dd 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group4/v2_md5_to_mv.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group4/v2_md5_to_mv.test.ts @@ -26,6 +26,7 @@ import '../jest_matchers'; const logFilePath = Path.join(__dirname, 'v2_md5_to_mv.test.log'); const SOME_TYPE = createType({ + switchToModelVersionAt: '8.10.0', name: 'some-type', modelVersions: { 1: { @@ -41,6 +42,7 @@ const SOME_TYPE = createType({ }); const ANOTHER_TYPE = createType({ + switchToModelVersionAt: '8.10.0', name: 'another-type', modelVersions: { '1': { @@ -55,6 +57,7 @@ const ANOTHER_TYPE = createType({ }, }); const ANOTHER_TYPE_UPDATED = createType({ + switchToModelVersionAt: '8.10.0', name: 'another-type', modelVersions: { '1': { diff --git a/src/core/server/integration_tests/saved_objects/migrations/group4/v2_with_mv_same_stack_version.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group4/v2_with_mv_same_stack_version.test.ts index 82384e1728f0f..ad3079e2b9627 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group4/v2_with_mv_same_stack_version.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group4/v2_with_mv_same_stack_version.test.ts @@ -39,6 +39,7 @@ describe('V2 algorithm - using model versions - upgrade without stack version in name: 'test_mv', namespaceType: 'single', migrations: {}, + switchToModelVersionAt: '8.8.0', modelVersions: { 1: { changes: [], diff --git a/src/core/server/integration_tests/saved_objects/migrations/group4/v2_with_mv_stack_version_bump.test.ts b/src/core/server/integration_tests/saved_objects/migrations/group4/v2_with_mv_stack_version_bump.test.ts index 402f9efe81caf..60353fd1d12b4 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/group4/v2_with_mv_stack_version_bump.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/group4/v2_with_mv_stack_version_bump.test.ts @@ -54,6 +54,7 @@ describe('V2 algorithm - using model versions - stack version bump scenario', () if (!beforeUpgrade) { Object.assign>(type, { + switchToModelVersionAt: '8.8.0', modelVersions: { 1: { changes: [ @@ -90,6 +91,7 @@ describe('V2 algorithm - using model versions - stack version bump scenario', () name: 'test_mv', namespaceType: 'single', migrations: {}, + switchToModelVersionAt: '8.8.0', modelVersions: { 1: { changes: [], diff --git a/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.fixtures.ts b/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.fixtures.ts index ce5b3b1120608..5b5e6db966ab9 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.fixtures.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/kibana_migrator_test_kit.fixtures.ts @@ -39,6 +39,7 @@ const defaultType: SavedObjectsType = { changes: [], }, }, + switchToModelVersionAt: '8.10.0', migrations: {}, }; diff --git a/src/core/server/integration_tests/saved_objects/migrations/zdt_1/basic_downgrade.test.ts b/src/core/server/integration_tests/saved_objects/migrations/zdt_1/basic_downgrade.test.ts index 11566e0f5ebf0..9523f6723fecb 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/zdt_1/basic_downgrade.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/zdt_1/basic_downgrade.test.ts @@ -39,6 +39,7 @@ describe('ZDT upgrades - basic downgrade', () => { keyword: { type: 'keyword' }, }, }, + switchToModelVersionAt: '8.0.0', modelVersions: { 1: { changes: [], @@ -55,6 +56,7 @@ describe('ZDT upgrades - basic downgrade', () => { newField1: { type: 'text' }, }, }, + switchToModelVersionAt: '8.0.0', modelVersions: { 1: { changes: [], diff --git a/src/core/server/integration_tests/saved_objects/migrations/zdt_2/outdated_doc_query.test.ts b/src/core/server/integration_tests/saved_objects/migrations/zdt_2/outdated_doc_query.test.ts index 7e7ad5a4d6573..da41ce206332b 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/zdt_2/outdated_doc_query.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/zdt_2/outdated_doc_query.test.ts @@ -52,6 +52,7 @@ describe('getOutdatedDocumentsQuery', () => { return createType({ name: 'test-type', + switchToModelVersionAt: '8.0.0', modelVersions, mappings: { dynamic: false, diff --git a/src/core/server/integration_tests/saved_objects/migrations/zdt_2/sor_higher_version_docs.test.ts b/src/core/server/integration_tests/saved_objects/migrations/zdt_2/sor_higher_version_docs.test.ts index 8fcabdf22797e..4c4d208a6af05 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/zdt_2/sor_higher_version_docs.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/zdt_2/sor_higher_version_docs.test.ts @@ -26,6 +26,7 @@ describe('Higher version doc conversion', () => { const getTestType = () => { return createType({ name: 'test-type', + switchToModelVersionAt: '8.0.0', modelVersions: { 1: { changes: [], diff --git a/src/core/server/integration_tests/saved_objects/migrations/zdt_2/v2_to_zdt_partial_failure.test.ts b/src/core/server/integration_tests/saved_objects/migrations/zdt_2/v2_to_zdt_partial_failure.test.ts index ec7bd0202da84..093b18eee9b56 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/zdt_2/v2_to_zdt_partial_failure.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/zdt_2/v2_to_zdt_partial_failure.test.ts @@ -47,6 +47,7 @@ describe('ZDT with v2 compat - recovering from partially migrated state', () => const typeFailingBetween = createType({ ...typeBefore, + switchToModelVersionAt: '8.0.0', modelVersions: { 1: { changes: [ @@ -71,6 +72,7 @@ describe('ZDT with v2 compat - recovering from partially migrated state', () => const typeAfter = createType({ ...typeBefore, + switchToModelVersionAt: '8.0.0', modelVersions: { 1: { changes: [ diff --git a/src/core/server/integration_tests/saved_objects/migrations/zdt_v2_compat/switch_to_model_version.test.ts b/src/core/server/integration_tests/saved_objects/migrations/zdt_v2_compat/switch_to_model_version.test.ts index e313182b693f3..4aff713b19d78 100644 --- a/src/core/server/integration_tests/saved_objects/migrations/zdt_v2_compat/switch_to_model_version.test.ts +++ b/src/core/server/integration_tests/saved_objects/migrations/zdt_v2_compat/switch_to_model_version.test.ts @@ -68,6 +68,7 @@ describe('ZDT with v2 compat - type switching from migration to model version', }; }, }, + switchToModelVersionAt: '8.0.0', modelVersions: { 1: { changes: [ diff --git a/src/core/server/integration_tests/saved_objects/service/lib/bulk_update.test.ts b/src/core/server/integration_tests/saved_objects/service/lib/bulk_update.test.ts index e961f11c7021a..986a06b57f92d 100644 --- a/src/core/server/integration_tests/saved_objects/service/lib/bulk_update.test.ts +++ b/src/core/server/integration_tests/saved_objects/service/lib/bulk_update.test.ts @@ -73,6 +73,7 @@ describe('SOR - bulk_update API', () => { management: { importableAndExportable: true, }, + switchToModelVersionAt: '8.10.0', modelVersions: versionMap, }; }; @@ -116,6 +117,7 @@ describe('SOR - bulk_update API', () => { management: { importableAndExportable: true, }, + switchToModelVersionAt: '8.10.0', modelVersions: versionOtherMap, }; }; @@ -132,6 +134,7 @@ describe('SOR - bulk_update API', () => { management: { importableAndExportable: true, }, + switchToModelVersionAt: '8.10.0', modelVersions: {}, }; }; diff --git a/src/core/server/integration_tests/saved_objects/service/lib/update.test.ts b/src/core/server/integration_tests/saved_objects/service/lib/update.test.ts index 95d34b1403d85..bf83b2cfd07ea 100644 --- a/src/core/server/integration_tests/saved_objects/service/lib/update.test.ts +++ b/src/core/server/integration_tests/saved_objects/service/lib/update.test.ts @@ -69,6 +69,7 @@ describe('SOR - update API', () => { management: { importableAndExportable: true, }, + switchToModelVersionAt: '8.10.0', modelVersions: versionMap, }; }; @@ -85,6 +86,7 @@ describe('SOR - update API', () => { management: { importableAndExportable: true, }, + switchToModelVersionAt: '8.10.0', modelVersions: {}, }; }; diff --git a/src/core/test-helpers/model-versions/src/model_version_tester.ts b/src/core/test-helpers/model-versions/src/model_version_tester.ts index 7c30aa355b5e0..31553a0f4edc3 100644 --- a/src/core/test-helpers/model-versions/src/model_version_tester.ts +++ b/src/core/test-helpers/model-versions/src/model_version_tester.ts @@ -15,6 +15,7 @@ import type { SavedObjectsType, SavedObject } from '@kbn/core-saved-objects-serv import { modelVersionToVirtualVersion, SavedObjectTypeRegistry, + globalSwitchToModelVersionAt, } from '@kbn/core-saved-objects-base-server-internal'; import { DocumentMigrator } from '@kbn/core-saved-objects-migration-server-internal'; @@ -80,7 +81,10 @@ export const createModelVersionTestMigrator = ({ type: SavedObjectsType; }): ModelVersionTestMigrator => { const typeRegistry = new SavedObjectTypeRegistry(); - typeRegistry.registerType(type); + typeRegistry.registerType({ + switchToModelVersionAt: globalSwitchToModelVersionAt, + ...type, + }); const logger = loggerMock.create(); diff --git a/x-pack/platform/plugins/shared/cases/server/saved_object_types/cases/cases.ts b/x-pack/platform/plugins/shared/cases/server/saved_object_types/cases/cases.ts index 518c51fef2f8b..0cf1905ca0cf4 100644 --- a/x-pack/platform/plugins/shared/cases/server/saved_object_types/cases/cases.ts +++ b/x-pack/platform/plugins/shared/cases/server/saved_object_types/cases/cases.ts @@ -24,6 +24,7 @@ export const createCaseSavedObjectType = ( logger: Logger ): SavedObjectsType => ({ name: CASE_SAVED_OBJECT, + switchToModelVersionAt: '8.10.0', indexPattern: ALERTING_CASES_SAVED_OBJECT_INDEX, hidden: true, namespaceType: 'multiple-isolated', diff --git a/x-pack/solutions/observability/plugins/slo/server/saved_objects/slo.ts b/x-pack/solutions/observability/plugins/slo/server/saved_objects/slo.ts index dd41f9031de26..1b594db90ae79 100644 --- a/x-pack/solutions/observability/plugins/slo/server/saved_objects/slo.ts +++ b/x-pack/solutions/observability/plugins/slo/server/saved_objects/slo.ts @@ -36,6 +36,7 @@ export const slo: SavedObjectsType = { name: SO_SLO_TYPE, hidden: false, namespaceType: 'multiple-isolated', + switchToModelVersionAt: '8.10.0', modelVersions: { 1: { changes: [ diff --git a/x-pack/test/encrypted_saved_objects_api_integration/plugins/api_consumer_plugin/server/index.ts b/x-pack/test/encrypted_saved_objects_api_integration/plugins/api_consumer_plugin/server/index.ts index 817a13a5d3d47..19781d61bbc5e 100644 --- a/x-pack/test/encrypted_saved_objects_api_integration/plugins/api_consumer_plugin/server/index.ts +++ b/x-pack/test/encrypted_saved_objects_api_integration/plugins/api_consumer_plugin/server/index.ts @@ -317,6 +317,7 @@ function defineModelVersionWithMigration(core: CoreSetup, deps: Pl hidden: false, management: { importableAndExportable: true }, namespaceType: 'multiple-isolated', + switchToModelVersionAt: '8.10.0', mappings: { properties: { nonEncryptedAttribute: {