Skip to content

Commit

Permalink
Merge branch 'main' into log-explorer-testing
Browse files Browse the repository at this point in the history
  • Loading branch information
tonyghiani authored Oct 4, 2023
2 parents 4ff1893 + dfd35c6 commit 02494af
Show file tree
Hide file tree
Showing 39 changed files with 540 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,16 @@ export interface DocumentMigrateOptions {
* Defaults to `false`.
*/
allowDowngrade?: boolean;
/**
* If specified, will migrate to the given version instead of the latest known version.
*/
targetTypeVersion?: string;
}

interface TransformOptions {
convertNamespaceTypes?: boolean;
allowDowngrade?: boolean;
targetTypeVersion?: string;
}

interface DocumentMigratorOptions {
Expand Down Expand Up @@ -149,10 +154,11 @@ export class DocumentMigrator implements VersionedTransformer {
*/
public migrate(
doc: SavedObjectUnsanitizedDoc,
{ allowDowngrade = false }: DocumentMigrateOptions = {}
{ allowDowngrade = false, targetTypeVersion }: DocumentMigrateOptions = {}
): SavedObjectUnsanitizedDoc {
const { document } = this.transform(doc, {
allowDowngrade,
targetTypeVersion,
});
return document;
}
Expand All @@ -171,36 +177,45 @@ export class DocumentMigrator implements VersionedTransformer {

private transform(
doc: SavedObjectUnsanitizedDoc,
{ convertNamespaceTypes = false, allowDowngrade = false }: TransformOptions = {}
{
convertNamespaceTypes = false,
allowDowngrade = false,
targetTypeVersion,
}: TransformOptions = {}
) {
if (!this.migrations) {
throw new Error('Migrations are not ready. Make sure prepareMigrations is called first.');
}
const typeMigrations = this.migrations[doc.type];
if (downgradeRequired(doc, typeMigrations?.latestVersion ?? {})) {
if (downgradeRequired(doc, typeMigrations?.latestVersion ?? {}, targetTypeVersion)) {
const currentVersion = doc.typeMigrationVersion ?? doc.migrationVersion?.[doc.type];
const latestVersion = this.migrations[doc.type].latestVersion[TransformType.Migrate];
const latestVersion =
targetTypeVersion ?? this.migrations[doc.type].latestVersion[TransformType.Migrate];
if (!allowDowngrade) {
throw Boom.badData(
`Document "${doc.id}" belongs to a more recent version of Kibana [${currentVersion}] when the last known version is [${latestVersion}].`
);
}
return this.transformDown(doc, { targetTypeVersion: latestVersion! });
} else {
return this.transformUp(doc, { convertNamespaceTypes });
return this.transformUp(doc, { convertNamespaceTypes, targetTypeVersion });
}
}

private transformUp(
doc: SavedObjectUnsanitizedDoc,
{ convertNamespaceTypes }: { convertNamespaceTypes: boolean }
{
convertNamespaceTypes,
targetTypeVersion,
}: { convertNamespaceTypes: boolean; targetTypeVersion?: string }
) {
if (!this.migrations) {
throw new Error('Migrations are not ready. Make sure prepareMigrations is called first.');
}

const pipeline = new DocumentUpgradePipeline({
document: doc,
targetTypeVersion,
migrations: this.migrations,
kibanaVersion: this.options.kibanaVersion,
convertNamespaceTypes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,40 @@ describe('downgradeRequired', () => {

expect(downgradeRequired(doc, latestVersions)).toEqual(false);
});

it('returns true when targetTypeVersion is specified and lower than the document version', () => {
const doc = createDoc({
typeMigrationVersion: '8.0.0',
});
const latestVersions = {
[TransformType.Migrate]: '8.5.0',
} as Record<TransformType, string>;
const targetTypeVersion = '7.9.0';

expect(downgradeRequired(doc, latestVersions, targetTypeVersion)).toEqual(true);
});

it('returns false when targetTypeVersion is specified and higher than the document version', () => {
const doc = createDoc({
typeMigrationVersion: '8.0.0',
});
const latestVersions = {
[TransformType.Migrate]: '7.9.0',
} as Record<TransformType, string>;
const targetTypeVersion = '8.5.0';

expect(downgradeRequired(doc, latestVersions, targetTypeVersion)).toEqual(false);
});

it('returns false when targetTypeVersion is specified and the same as the document version', () => {
const doc = createDoc({
typeMigrationVersion: '8.0.0',
});
const latestVersions = {
[TransformType.Migrate]: '7.9.0',
} as Record<TransformType, string>;
const targetTypeVersion = '8.0.0';

expect(downgradeRequired(doc, latestVersions, targetTypeVersion)).toEqual(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,14 @@ export function transformComparator(a: Transform, b: Transform) {
*/
export function downgradeRequired(
doc: SavedObjectUnsanitizedDoc,
latestVersions: Record<TransformType, string>
latestVersions: Record<TransformType, string>,
targetTypeVersion?: string
): boolean {
const docTypeVersion = doc.typeMigrationVersion ?? doc.migrationVersion?.[doc.type];
const latestMigrationVersion = maxVersion(
latestVersions[TransformType.Migrate],
latestVersions[TransformType.Convert]
);
const latestMigrationVersion =
targetTypeVersion ??
maxVersion(latestVersions[TransformType.Migrate], latestVersions[TransformType.Convert]);

if (!docTypeVersion || !latestMigrationVersion) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,44 @@
# @kbn/core-test-helpers-model-versions

Package exposing utilities for model version integration testing.
Package exposing utilities for model version testing:
- unit testing
- integration testing

## Unit testing

### Model version test migrator

The `createModelVersionTestMigrator` helper allows to create a test migrator that
can be used to test model version changes between versions.

```ts
const mySoType = someSoType();
const migrator = createModelVersionTestMigrator({ type: mySoType });

const obj = createSomeSavedObject();

const migrated = migrator.migrate({
document: obj,
fromVersion: 1,
toVersion: 2,
});

expect(migrated.properties).toEqual(myExpectedProperties);
```

Please refer to the code documentation for more detailed examples.

## Integration testing

### Model version test bed

This package exposes a `createModelVersionTestBed` utility which allow simulating
a testbed environment where we're in the cohabitation period between two versions, to test the interactions
between two model versions of a set of SO types.

### Limitations:
Please refer to the code documentation for more detailed examples.

*Limitations:*

Because the test bed is only creating the parts of Core required to create the two SO
repositories, and because we're not loading all plugins (for proper isolation), the integration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
* Side Public License, v 1.
*/

export { createModelVersionTestBed } from './src/test_bed';

export type {
ModelVersionTestBed,
ModelVersionTestKit,
ModelVersionTestkitOptions,
SavedObjectTestkitDefinition,
} from './src/types';
export {
createModelVersionTestBed,
type ModelVersionTestBed,
type ModelVersionTestKit,
type ModelVersionTestkitOptions,
type SavedObjectTestkitDefinition,
} from './src/test_bed';
export {
createModelVersionTestMigrator,
type ModelVersionTestMigrator,
} from './src/model_version_tester';
Loading

0 comments on commit 02494af

Please sign in to comment.