diff --git a/src/server/saved_objects/migrations/core/determine_migration_action.test.ts b/src/server/saved_objects/migrations/core/determine_migration_action.test.ts index ee6016dcf9192..7516d17fd5e74 100644 --- a/src/server/saved_objects/migrations/core/determine_migration_action.test.ts +++ b/src/server/saved_objects/migrations/core/determine_migration_action.test.ts @@ -63,7 +63,30 @@ describe('determineMigrationAction', () => { doc: { dynamic: 'strict', properties: { - hello: { dynamic: true, goober: 'pea' }, + hello: { dynamic: 'true', goober: 'pea' }, + world: { baz: 'bing' }, + }, + }, + }; + + expect(determineMigrationAction(actual, expected)).toEqual(MigrationAction.None); + }); + + test('requires no action if mappings differ only by equivalent coerced properties', () => { + const actual = { + doc: { + dynamic: 'strict', + properties: { + hello: { dynamic: 'false', baz: '2', foo: 'bar' }, + world: { baz: 'bing' }, + }, + }, + }; + const expected = { + doc: { + dynamic: 'strict', + properties: { + hello: { dynamic: false, baz: 2, foo: 'bar' }, world: { baz: 'bing' }, }, }, diff --git a/src/server/saved_objects/migrations/core/determine_migration_action.ts b/src/server/saved_objects/migrations/core/determine_migration_action.ts index 1c7a6f9568d1e..72d3a4b652fef 100644 --- a/src/server/saved_objects/migrations/core/determine_migration_action.ts +++ b/src/server/saved_objects/migrations/core/determine_migration_action.ts @@ -74,7 +74,11 @@ function diffSubProperty(actual: any, expected: any): MigrationAction { // We have a leaf property, so we do a comparison. A change (e.g. 'text' -> 'keyword') // should result in a migration. if (typeof actual !== 'object') { - return _.isEqual(actual, expected) ? MigrationAction.None : MigrationAction.Migrate; + // We perform a string comparison here, because Elasticsearch coerces some primitives + // to string (such as dynamic: true and dynamic: 'true'), so we report a mapping + // equivalency if the string comparison checks out. This does mean that {} === '[object Object]' + // by this logic, but that is an edge case which should not occur in mapping definitions. + return `${actual}` === `${expected}` ? MigrationAction.None : MigrationAction.Migrate; } // Recursively compare the sub properties @@ -87,5 +91,5 @@ function diffSubProperty(actual: any, expected: any): MigrationAction { } function isDynamic(prop: any) { - return prop.dynamic === true || prop.dynamic === 'true'; + return prop && `${prop.dynamic}` === 'true'; }