Skip to content

Commit

Permalink
Skip transformations on unknown types
Browse files Browse the repository at this point in the history
  • Loading branch information
joshdover committed Jul 12, 2021
1 parent 4aa3f3f commit d71d94f
Show file tree
Hide file tree
Showing 4 changed files with 264 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,15 @@ describe('migrateRawDocsSafely', () => {
const transform = jest.fn<any, any>((doc: any) => [
set(_.cloneDeep(doc), 'attributes.name', 'HOI!'),
]);
const task = migrateRawDocsSafely(
new SavedObjectsSerializer(new SavedObjectTypeRegistry()),
transform,
[
const task = migrateRawDocsSafely({
serializer: new SavedObjectsSerializer(new SavedObjectTypeRegistry()),
knownTypes: new Set(['a', 'c']),
migrateDoc: transform,
rawDocs: [
{ _id: 'a:b', _source: { type: 'a', a: { name: 'AAA' } } },
{ _id: 'c:d', _source: { type: 'c', c: { name: 'DDD' } } },
]
);
],
});
const result = (await task()) as Either.Right<DocumentsTransformSuccess>;
expect(result._tag).toEqual('Right');
expect(result.right.processedDocs).toEqual([
Expand Down Expand Up @@ -181,14 +182,15 @@ describe('migrateRawDocsSafely', () => {
const transform = jest.fn<any, any>((doc: any) => [
set(_.cloneDeep(doc), 'attributes.name', 'TADA'),
]);
const task = migrateRawDocsSafely(
new SavedObjectsSerializer(new SavedObjectTypeRegistry()),
transform,
[
const task = migrateRawDocsSafely({
serializer: new SavedObjectsSerializer(new SavedObjectTypeRegistry()),
knownTypes: new Set(['a', 'c']),
migrateDoc: transform,
rawDocs: [
{ _id: 'foo:b', _source: { type: 'a', a: { name: 'AAA' } } },
{ _id: 'c:d', _source: { type: 'c', c: { name: 'DDD' } } },
]
);
],
});
const result = (await task()) as Either.Left<DocumentsTransformFailed>;
expect(transform).toHaveBeenCalledTimes(1);
expect(result._tag).toEqual('Left');
Expand All @@ -202,11 +204,12 @@ describe('migrateRawDocsSafely', () => {
set(_.cloneDeep(doc), 'attributes.name', 'HOI!'),
{ id: 'bar', type: 'foo', attributes: { name: 'baz' } },
]);
const task = migrateRawDocsSafely(
new SavedObjectsSerializer(new SavedObjectTypeRegistry()),
transform,
[{ _id: 'a:b', _source: { type: 'a', a: { name: 'AAA' } } }]
);
const task = migrateRawDocsSafely({
serializer: new SavedObjectsSerializer(new SavedObjectTypeRegistry()),
knownTypes: new Set(['a', 'c']),
migrateDoc: transform,
rawDocs: [{ _id: 'a:b', _source: { type: 'a', a: { name: 'AAA' } } }],
});
const result = (await task()) as Either.Right<DocumentsTransformSuccess>;
expect(result._tag).toEqual('Right');
expect(result.right.processedDocs).toEqual([
Expand Down Expand Up @@ -235,11 +238,12 @@ describe('migrateRawDocsSafely', () => {
const transform = jest.fn<any, any>((doc: any) => {
throw new TransformSavedObjectDocumentError(new Error('error during transform'), '8.0.0');
});
const task = migrateRawDocsSafely(
new SavedObjectsSerializer(new SavedObjectTypeRegistry()),
transform,
[{ _id: 'a:b', _source: { type: 'a', a: { name: 'AAA' } } }] // this is the raw doc
);
const task = migrateRawDocsSafely({
serializer: new SavedObjectsSerializer(new SavedObjectTypeRegistry()),
knownTypes: new Set(['a', 'c']),
migrateDoc: transform,
rawDocs: [{ _id: 'a:b', _source: { type: 'a', a: { name: 'AAA' } } }], // this is the raw doc
});
const result = (await task()) as Either.Left<DocumentsTransformFailed>;
expect(transform).toHaveBeenCalledTimes(1);
expect(result._tag).toEqual('Left');
Expand All @@ -252,4 +256,43 @@ describe('migrateRawDocsSafely', () => {
}
`);
});

test('skips documents of unknown types', async () => {
const transform = jest.fn<any, any>((doc: any) => [
set(_.cloneDeep(doc), 'attributes.name', 'HOI!'),
]);
const task = migrateRawDocsSafely({
serializer: new SavedObjectsSerializer(new SavedObjectTypeRegistry()),
knownTypes: new Set(['a']),
migrateDoc: transform,
rawDocs: [
{ _id: 'a:b', _source: { type: 'a', a: { name: 'AAA' } } },
{ _id: 'c:d', _source: { type: 'c', c: { name: 'DDD' } } },
],
});

const result = (await task()) as Either.Right<DocumentsTransformSuccess>;
expect(result._tag).toEqual('Right');
expect(result.right.processedDocs).toEqual([
{
_id: 'a:b',
_source: { type: 'a', a: { name: 'HOI!' }, migrationVersion: {}, references: [] },
},
{
_id: 'c:d',
// name field is not migrated on unknown type
_source: { type: 'c', c: { name: 'DDD' } },
},
]);

const obj1 = {
id: 'b',
type: 'a',
attributes: { name: 'AAA' },
migrationVersion: {},
references: [],
};
expect(transform).toHaveBeenCalledTimes(1);
expect(transform).toHaveBeenNthCalledWith(1, obj1);
});
});
26 changes: 20 additions & 6 deletions src/core/server/saved_objects/migrations/core/migrate_raw_docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,26 +81,40 @@ export async function migrateRawDocs(
return processedDocs;
}

interface MigrateRawDocsSafelyDeps {
serializer: SavedObjectsSerializer;
knownTypes: ReadonlySet<string>;
migrateDoc: MigrateAndConvertFn;
rawDocs: SavedObjectsRawDoc[];
}

/**
* Applies the specified migration function to every saved object document provided
* and converts the saved object to a raw document.
* Captures the ids and errors from any documents that are not valid saved objects or
* for which the transformation function failed.
* @returns {TaskEither.TaskEither<DocumentsTransformFailed, DocumentsTransformSuccess>}
*/
export function migrateRawDocsSafely(
serializer: SavedObjectsSerializer,
migrateDoc: MigrateAndConvertFn,
rawDocs: SavedObjectsRawDoc[]
): TaskEither.TaskEither<DocumentsTransformFailed, DocumentsTransformSuccess> {
export function migrateRawDocsSafely({
serializer,
knownTypes,
migrateDoc,
rawDocs,
}: MigrateRawDocsSafelyDeps): TaskEither.TaskEither<
DocumentsTransformFailed,
DocumentsTransformSuccess
> {
return async () => {
const migrateDocNonBlocking = transformNonBlocking(migrateDoc);
const processedDocs: SavedObjectsRawDoc[] = [];
const transformErrors: TransformErrorObjects[] = [];
const corruptSavedObjectIds: string[] = [];
const options = { namespaceTreatment: 'lax' as const };
for (const raw of rawDocs) {
if (serializer.isRawSavedObject(raw, options)) {
// Do not transform documents of unknown types
if (raw?._source?.type && !knownTypes.has(raw._source.type)) {
processedDocs.push(raw);
} else if (serializer.isRawSavedObject(raw, options)) {
try {
const savedObject = convertToRawAddMigrationVersion(raw, options, serializer);
processedDocs.push(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,12 @@ export class KibanaMigrator {
logger: this.log,
preMigrationScript: indexMap[index].script,
transformRawDocs: (rawDocs: SavedObjectsRawDoc[]) =>
migrateRawDocsSafely(
this.serializer,
this.documentMigrator.migrateAndConvert,
rawDocs
),
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,
Expand Down
Loading

0 comments on commit d71d94f

Please sign in to comment.