mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Migrations] Add migrationVersion
property to the Saved Objects API output (#154364)
This commit is contained in:
parent
42a893db40
commit
768fe1af31
40 changed files with 353 additions and 106 deletions
|
@ -19,7 +19,12 @@ export type { SavedObjectsFindOptionsReference } from '@kbn/core-saved-objects-a
|
|||
*/
|
||||
export type SavedObjectsFindOptions = Omit<
|
||||
SavedObjectFindOptionsServer,
|
||||
'pit' | 'rootSearchFields' | 'searchAfter' | 'sortOrder' | 'typeToNamespacesMap'
|
||||
| 'pit'
|
||||
| 'rootSearchFields'
|
||||
| 'searchAfter'
|
||||
| 'sortOrder'
|
||||
| 'typeToNamespacesMap'
|
||||
| 'migrationVersionCompatibility'
|
||||
>;
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,8 +10,8 @@ import type { MgetResponseItem } from '@elastic/elasticsearch/lib/api/typesWithB
|
|||
|
||||
import { isNotFoundFromUnsupportedServer } from '@kbn/core-elasticsearch-server-internal';
|
||||
import type {
|
||||
SavedObjectsBaseOptions,
|
||||
SavedObjectsBulkResolveObject,
|
||||
SavedObjectsResolveOptions,
|
||||
SavedObjectsResolveResponse,
|
||||
SavedObjectsIncrementCounterField,
|
||||
SavedObjectsIncrementCounterOptions,
|
||||
|
@ -70,7 +70,7 @@ export interface InternalBulkResolveParams {
|
|||
encryptionExtension: ISavedObjectsEncryptionExtension | undefined;
|
||||
securityExtension: ISavedObjectsSecurityExtension | undefined;
|
||||
objects: SavedObjectsBulkResolveObject[];
|
||||
options?: SavedObjectsBaseOptions;
|
||||
options?: SavedObjectsResolveOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,6 +115,7 @@ export async function internalBulkResolve<T>(
|
|||
const validObjects = allObjects.filter(isRight);
|
||||
|
||||
const namespace = normalizeNamespace(options.namespace);
|
||||
const { migrationVersionCompatibility } = options;
|
||||
|
||||
const aliasDocs = await fetchAndUpdateAliases(
|
||||
validObjects,
|
||||
|
@ -178,7 +179,9 @@ export async function internalBulkResolve<T>(
|
|||
) {
|
||||
// Encryption
|
||||
// @ts-expect-error MultiGetHit._source is optional
|
||||
const object = getSavedObjectFromSource<T>(registry, objectType, objectId, doc);
|
||||
const object = getSavedObjectFromSource<T>(registry, objectType, objectId, doc, {
|
||||
migrationVersionCompatibility,
|
||||
});
|
||||
if (!encryptionExtension?.isEncryptableType(object.type)) {
|
||||
return object;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { omit } from 'lodash';
|
||||
import type { SavedObjectsRawDoc } from '@kbn/core-saved-objects-server';
|
||||
import { ALL_NAMESPACES_STRING } from '@kbn/core-saved-objects-utils-server';
|
||||
import { encodeHitVersion } from '@kbn/core-saved-objects-base-server-internal';
|
||||
|
@ -170,6 +171,49 @@ describe('#getSavedObjectFromSource', () => {
|
|||
expect(result1).toEqual(expect.objectContaining({ namespaces: ['default'] }));
|
||||
expect(result2).toEqual(expect.objectContaining({ namespaces: ['foo-ns'] }));
|
||||
});
|
||||
|
||||
it('keeps original `migrationVersion` in compatibility mode', () => {
|
||||
const type = NAMESPACE_AGNOSTIC_TYPE;
|
||||
const doc = createRawDoc(type);
|
||||
const result = getSavedObjectFromSource(registry, type, id, doc, {
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
expect(result).toHaveProperty('migrationVersion', migrationVersion);
|
||||
});
|
||||
|
||||
it('derives `migrationVersion` in compatibility mode', () => {
|
||||
const type = NAMESPACE_AGNOSTIC_TYPE;
|
||||
const doc = omit(createRawDoc(type), '_source.migrationVersion');
|
||||
|
||||
const result = getSavedObjectFromSource(registry, type, id, doc, {
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
expect(result).toHaveProperty('migrationVersion', { [type]: typeMigrationVersion });
|
||||
});
|
||||
|
||||
it('does not derive `migrationVersion` in compatibility mode if there is no type version', () => {
|
||||
const type = NAMESPACE_AGNOSTIC_TYPE;
|
||||
const doc = omit(
|
||||
createRawDoc(type),
|
||||
'_source.migrationVersion',
|
||||
'_source.typeMigrationVersion'
|
||||
);
|
||||
|
||||
const result = getSavedObjectFromSource(registry, type, id, doc, {
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
expect(result).toHaveProperty('migrationVersion', undefined);
|
||||
});
|
||||
|
||||
it('does not derive `migrationVersion` in raw mode', () => {
|
||||
const type = NAMESPACE_AGNOSTIC_TYPE;
|
||||
const doc = omit(createRawDoc(type), '_source.migrationVersion');
|
||||
|
||||
const result = getSavedObjectFromSource(registry, type, id, doc, {
|
||||
migrationVersionCompatibility: 'raw',
|
||||
});
|
||||
expect(result).toHaveProperty('migrationVersion', undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#rawDocExistsInNamespace', () => {
|
||||
|
|
|
@ -13,6 +13,7 @@ import {
|
|||
type SavedObjectsRawDocSource,
|
||||
type SavedObject,
|
||||
SavedObjectsErrorHelpers,
|
||||
type SavedObjectsRawDocParseOptions,
|
||||
} from '@kbn/core-saved-objects-server';
|
||||
import { SavedObjectsUtils, ALL_NAMESPACES_STRING } from '@kbn/core-saved-objects-utils-server';
|
||||
import {
|
||||
|
@ -112,6 +113,14 @@ export function getExpectedVersionProperties(version?: string, document?: SavedO
|
|||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface GetSavedObjectFromSourceOptions {
|
||||
/** {@link SavedObjectsRawDocParseOptions.migrationVersionCompatibility} */
|
||||
migrationVersionCompatibility?: SavedObjectsRawDocParseOptions['migrationVersionCompatibility'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a saved object from a raw ES document.
|
||||
*
|
||||
|
@ -126,9 +135,19 @@ export function getSavedObjectFromSource<T>(
|
|||
registry: ISavedObjectTypeRegistry,
|
||||
type: string,
|
||||
id: string,
|
||||
doc: { _seq_no?: number; _primary_term?: number; _source: SavedObjectsRawDocSource }
|
||||
doc: { _seq_no?: number; _primary_term?: number; _source: SavedObjectsRawDocSource },
|
||||
{ migrationVersionCompatibility = 'raw' }: GetSavedObjectFromSourceOptions = {}
|
||||
): SavedObject<T> {
|
||||
const { originId, updated_at: updatedAt, created_at: createdAt } = doc._source;
|
||||
const {
|
||||
originId,
|
||||
updated_at: updatedAt,
|
||||
created_at: createdAt,
|
||||
coreMigrationVersion,
|
||||
typeMigrationVersion,
|
||||
migrationVersion = migrationVersionCompatibility === 'compatible' && typeMigrationVersion
|
||||
? { [type]: typeMigrationVersion }
|
||||
: undefined,
|
||||
} = doc._source;
|
||||
|
||||
let namespaces: string[] = [];
|
||||
if (!registry.isNamespaceAgnostic(type)) {
|
||||
|
@ -141,15 +160,15 @@ export function getSavedObjectFromSource<T>(
|
|||
id,
|
||||
type,
|
||||
namespaces,
|
||||
migrationVersion,
|
||||
coreMigrationVersion,
|
||||
typeMigrationVersion,
|
||||
...(originId && { originId }),
|
||||
...(updatedAt && { updated_at: updatedAt }),
|
||||
...(createdAt && { created_at: createdAt }),
|
||||
version: encodeHitVersion(doc),
|
||||
attributes: doc._source[type],
|
||||
references: doc._source.references || [],
|
||||
migrationVersion: doc._source.migrationVersion,
|
||||
coreMigrationVersion: doc._source.coreMigrationVersion,
|
||||
typeMigrationVersion: doc._source.typeMigrationVersion,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -929,25 +929,35 @@ describe('SavedObjectsRepository', () => {
|
|||
});
|
||||
|
||||
// Assert that both raw docs from the ES response are deserialized
|
||||
expect(serializer.rawToSavedObject).toHaveBeenNthCalledWith(1, {
|
||||
...response.items[0].create,
|
||||
_source: {
|
||||
...response.items[0].create._source,
|
||||
namespaces: response.items[0].create._source.namespaces,
|
||||
coreMigrationVersion: expect.any(String),
|
||||
typeMigrationVersion: '1.1.1',
|
||||
expect(serializer.rawToSavedObject).toHaveBeenNthCalledWith(
|
||||
1,
|
||||
{
|
||||
...response.items[0].create,
|
||||
_source: {
|
||||
...response.items[0].create._source,
|
||||
namespaces: response.items[0].create._source.namespaces,
|
||||
coreMigrationVersion: expect.any(String),
|
||||
typeMigrationVersion: '1.1.1',
|
||||
},
|
||||
_id: expect.stringMatching(
|
||||
/^myspace:config:[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/
|
||||
),
|
||||
},
|
||||
_id: expect.stringMatching(/^myspace:config:[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}$/),
|
||||
});
|
||||
expect(serializer.rawToSavedObject).toHaveBeenNthCalledWith(2, {
|
||||
...response.items[1].create,
|
||||
_source: {
|
||||
...response.items[1].create._source,
|
||||
namespaces: response.items[1].create._source.namespaces,
|
||||
coreMigrationVersion: expect.any(String),
|
||||
typeMigrationVersion: '1.1.1',
|
||||
expect.any(Object)
|
||||
);
|
||||
expect(serializer.rawToSavedObject).toHaveBeenNthCalledWith(
|
||||
2,
|
||||
{
|
||||
...response.items[1].create,
|
||||
_source: {
|
||||
...response.items[1].create._source,
|
||||
namespaces: response.items[1].create._source.namespaces,
|
||||
coreMigrationVersion: expect.any(String),
|
||||
typeMigrationVersion: '1.1.1',
|
||||
},
|
||||
},
|
||||
});
|
||||
expect.any(Object)
|
||||
);
|
||||
|
||||
// Assert that ID's are deserialized to remove the type and namespace
|
||||
expect(result.saved_objects[0].id).toEqual(
|
||||
|
|
|
@ -17,7 +17,10 @@ import {
|
|||
isSupportedEsServer,
|
||||
isNotFoundFromUnsupportedServer,
|
||||
} from '@kbn/core-elasticsearch-server-internal';
|
||||
import type { BulkResolveError } from '@kbn/core-saved-objects-server';
|
||||
import type {
|
||||
BulkResolveError,
|
||||
SavedObjectsRawDocParseOptions,
|
||||
} from '@kbn/core-saved-objects-server';
|
||||
import type {
|
||||
SavedObjectsBaseOptions,
|
||||
SavedObjectsIncrementCounterOptions,
|
||||
|
@ -46,6 +49,7 @@ import type {
|
|||
SavedObjectsClosePointInTimeResponse,
|
||||
ISavedObjectsPointInTimeFinder,
|
||||
SavedObjectsCreatePointInTimeFinderDependencies,
|
||||
SavedObjectsResolveOptions,
|
||||
SavedObjectsResolveResponse,
|
||||
SavedObjectsCollectMultiNamespaceReferencesObject,
|
||||
SavedObjectsUpdateObjectsSpacesObject,
|
||||
|
@ -54,6 +58,7 @@ import type {
|
|||
SavedObjectsClosePointInTimeOptions,
|
||||
SavedObjectsCreatePointInTimeFinderOptions,
|
||||
SavedObjectsFindOptions,
|
||||
SavedObjectsGetOptions,
|
||||
SavedObjectsBulkDeleteObject,
|
||||
SavedObjectsBulkDeleteOptions,
|
||||
SavedObjectsBulkDeleteResponse,
|
||||
|
@ -310,6 +315,7 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
initialNamespaces,
|
||||
version,
|
||||
} = options;
|
||||
const { migrationVersionCompatibility } = options;
|
||||
if (!this._allowedTypes.includes(type)) {
|
||||
throw SavedObjectsErrorHelpers.createUnsupportedTypeError(type);
|
||||
}
|
||||
|
@ -418,7 +424,7 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
}
|
||||
|
||||
return this.optionallyDecryptAndRedactSingleResult(
|
||||
this._rawToSavedObject<T>({ ...raw, ...body }),
|
||||
this._rawToSavedObject<T>({ ...raw, ...body }, { migrationVersionCompatibility }),
|
||||
authorizationResult?.typeMap,
|
||||
attributes
|
||||
);
|
||||
|
@ -432,7 +438,11 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
options: SavedObjectsCreateOptions = {}
|
||||
): Promise<SavedObjectsBulkResponse<T>> {
|
||||
const namespace = this.getCurrentNamespace(options.namespace);
|
||||
const { overwrite = false, refresh = DEFAULT_REFRESH_SETTING } = options;
|
||||
const {
|
||||
migrationVersionCompatibility,
|
||||
overwrite = false,
|
||||
refresh = DEFAULT_REFRESH_SETTING,
|
||||
} = options;
|
||||
const time = getCurrentTime();
|
||||
|
||||
let preflightCheckIndexCounter = 0;
|
||||
|
@ -667,10 +677,13 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
// When method == 'index' the bulkResponse doesn't include the indexed
|
||||
// _source so we return rawMigratedDoc but have to spread the latest
|
||||
// _seq_no and _primary_term values from the rawResponse.
|
||||
return this._rawToSavedObject({
|
||||
...rawMigratedDoc,
|
||||
...{ _seq_no: rawResponse._seq_no, _primary_term: rawResponse._primary_term },
|
||||
});
|
||||
return this._rawToSavedObject(
|
||||
{
|
||||
...rawMigratedDoc,
|
||||
...{ _seq_no: rawResponse._seq_no, _primary_term: rawResponse._primary_term },
|
||||
},
|
||||
{ migrationVersionCompatibility }
|
||||
);
|
||||
}),
|
||||
};
|
||||
|
||||
|
@ -1295,6 +1308,7 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
filter,
|
||||
preference,
|
||||
aggs,
|
||||
migrationVersionCompatibility,
|
||||
} = options;
|
||||
|
||||
if (!type) {
|
||||
|
@ -1444,7 +1458,7 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
saved_objects: body.hits.hits.map(
|
||||
(hit: estypes.SearchHit<SavedObjectsRawDocSource>): SavedObjectsFindResult => ({
|
||||
// @ts-expect-error @elastic/elasticsearch _source is optional
|
||||
...this._rawToSavedObject(hit),
|
||||
...this._rawToSavedObject(hit, { migrationVersionCompatibility }),
|
||||
score: hit._score!,
|
||||
sort: hit.sort,
|
||||
})
|
||||
|
@ -1480,9 +1494,10 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
*/
|
||||
async bulkGet<T = unknown>(
|
||||
objects: SavedObjectsBulkGetObject[] = [],
|
||||
options: SavedObjectsBaseOptions = {}
|
||||
options: SavedObjectsGetOptions = {}
|
||||
): Promise<SavedObjectsBulkResponse<T>> {
|
||||
const namespace = this.getCurrentNamespace(options.namespace);
|
||||
const { migrationVersionCompatibility } = options;
|
||||
|
||||
if (objects.length === 0) {
|
||||
return { saved_objects: [] };
|
||||
|
@ -1628,7 +1643,9 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
}
|
||||
|
||||
// @ts-expect-error MultiGetHit._source is optional
|
||||
return getSavedObjectFromSource(this._registry, type, id, doc);
|
||||
return getSavedObjectFromSource(this._registry, type, id, doc, {
|
||||
migrationVersionCompatibility,
|
||||
});
|
||||
}),
|
||||
};
|
||||
|
||||
|
@ -1645,7 +1662,7 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
*/
|
||||
async bulkResolve<T = unknown>(
|
||||
objects: SavedObjectsBulkResolveObject[],
|
||||
options: SavedObjectsBaseOptions = {}
|
||||
options: SavedObjectsResolveOptions = {}
|
||||
): Promise<SavedObjectsBulkResolveResponse<T>> {
|
||||
const namespace = this.getCurrentNamespace(options.namespace);
|
||||
const { resolved_objects: bulkResults } = await internalBulkResolve<T>({
|
||||
|
@ -1681,9 +1698,10 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
async get<T = unknown>(
|
||||
type: string,
|
||||
id: string,
|
||||
options: SavedObjectsBaseOptions = {}
|
||||
options: SavedObjectsGetOptions = {}
|
||||
): Promise<SavedObject<T>> {
|
||||
const namespace = this.getCurrentNamespace(options.namespace);
|
||||
const { migrationVersionCompatibility } = options;
|
||||
|
||||
if (!this._allowedTypes.includes(type)) {
|
||||
throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id);
|
||||
|
@ -1719,7 +1737,9 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id);
|
||||
}
|
||||
|
||||
const result = getSavedObjectFromSource<T>(this._registry, type, id, body);
|
||||
const result = getSavedObjectFromSource<T>(this._registry, type, id, body, {
|
||||
migrationVersionCompatibility,
|
||||
});
|
||||
|
||||
return this.optionallyDecryptAndRedactSingleResult(result, authorizationResult?.typeMap);
|
||||
}
|
||||
|
@ -1730,7 +1750,7 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
async resolve<T = unknown>(
|
||||
type: string,
|
||||
id: string,
|
||||
options: SavedObjectsBaseOptions = {}
|
||||
options: SavedObjectsResolveOptions = {}
|
||||
): Promise<SavedObjectsResolveResponse<T>> {
|
||||
const namespace = this.getCurrentNamespace(options.namespace);
|
||||
const { resolved_objects: bulkResults } = await internalBulkResolve<T>({
|
||||
|
@ -2588,12 +2608,16 @@ export class SavedObjectsRepository implements ISavedObjectsRepository {
|
|||
return unique(types.map((t) => this.getIndexForType(t)));
|
||||
}
|
||||
|
||||
private _rawToSavedObject<T = unknown>(raw: SavedObjectsRawDoc): SavedObject<T> {
|
||||
const savedObject = this._serializer.rawToSavedObject(raw);
|
||||
private _rawToSavedObject<T = unknown>(
|
||||
raw: SavedObjectsRawDoc,
|
||||
options?: SavedObjectsRawDocParseOptions
|
||||
): SavedObject<T> {
|
||||
const savedObject = this._serializer.rawToSavedObject(raw, options);
|
||||
const { namespace, type } = savedObject;
|
||||
if (this._registry.isSingleNamespace(type)) {
|
||||
savedObject.namespaces = [SavedObjectsUtils.namespaceIdToString(namespace)];
|
||||
}
|
||||
|
||||
return omit(savedObject, ['namespace']) as SavedObject<T>;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import type {
|
|||
SavedObjectsBulkUpdateObject,
|
||||
ISavedObjectsPointInTimeFinder,
|
||||
SavedObjectsCreatePointInTimeFinderDependencies,
|
||||
SavedObjectsResolveOptions,
|
||||
SavedObjectsResolveResponse,
|
||||
SavedObjectsCollectMultiNamespaceReferencesObject,
|
||||
SavedObjectsUpdateObjectsSpacesObject,
|
||||
|
@ -39,6 +40,7 @@ import type {
|
|||
SavedObjectsClosePointInTimeOptions,
|
||||
SavedObjectsCreatePointInTimeFinderOptions,
|
||||
SavedObjectsFindOptions,
|
||||
SavedObjectsGetOptions,
|
||||
SavedObjectsBulkDeleteObject,
|
||||
SavedObjectsBulkDeleteOptions,
|
||||
SavedObjectsBulkDeleteResponse,
|
||||
|
@ -103,7 +105,7 @@ export class SavedObjectsClient implements SavedObjectsClientContract {
|
|||
/** {@inheritDoc SavedObjectsClientContract.bulkGet} */
|
||||
async bulkGet<T = unknown>(
|
||||
objects: SavedObjectsBulkGetObject[] = [],
|
||||
options: SavedObjectsBaseOptions = {}
|
||||
options: SavedObjectsGetOptions = {}
|
||||
): Promise<SavedObjectsBulkResponse<T>> {
|
||||
return await this._repository.bulkGet(objects, options);
|
||||
}
|
||||
|
@ -112,7 +114,7 @@ export class SavedObjectsClient implements SavedObjectsClientContract {
|
|||
async get<T = unknown>(
|
||||
type: string,
|
||||
id: string,
|
||||
options: SavedObjectsBaseOptions = {}
|
||||
options: SavedObjectsGetOptions = {}
|
||||
): Promise<SavedObject<T>> {
|
||||
return await this._repository.get(type, id, options);
|
||||
}
|
||||
|
@ -120,7 +122,7 @@ export class SavedObjectsClient implements SavedObjectsClientContract {
|
|||
/** {@inheritDoc SavedObjectsClientContract.bulkResolve} */
|
||||
async bulkResolve<T = unknown>(
|
||||
objects: SavedObjectsBulkResolveObject[],
|
||||
options?: SavedObjectsBaseOptions
|
||||
options?: SavedObjectsResolveOptions
|
||||
): Promise<SavedObjectsBulkResolveResponse<T>> {
|
||||
return await this._repository.bulkResolve(objects, options);
|
||||
}
|
||||
|
@ -129,7 +131,7 @@ export class SavedObjectsClient implements SavedObjectsClientContract {
|
|||
async resolve<T = unknown>(
|
||||
type: string,
|
||||
id: string,
|
||||
options: SavedObjectsBaseOptions = {}
|
||||
options: SavedObjectsResolveOptions = {}
|
||||
): Promise<SavedObjectsResolveResponse<T>> {
|
||||
return await this._repository.resolve(type, id, options);
|
||||
}
|
||||
|
|
|
@ -384,21 +384,20 @@ export const createRegistry = () => {
|
|||
};
|
||||
|
||||
export const createSpySerializer = (registry: SavedObjectTypeRegistry) => {
|
||||
const spyInstance = {
|
||||
isRawSavedObject: jest.fn(),
|
||||
rawToSavedObject: jest.fn(),
|
||||
savedObjectToRaw: jest.fn(),
|
||||
generateRawId: jest.fn(),
|
||||
generateRawLegacyUrlAliasId: jest.fn(),
|
||||
trimIdPrefix: jest.fn(),
|
||||
};
|
||||
const realInstance = new SavedObjectsSerializer(registry);
|
||||
Object.keys(spyInstance).forEach((key) => {
|
||||
// @ts-expect-error no proper way to do this with typing support
|
||||
spyInstance[key].mockImplementation((...args) => realInstance[key](...args));
|
||||
});
|
||||
const serializer = new SavedObjectsSerializer(registry);
|
||||
|
||||
return spyInstance as unknown as jest.Mocked<SavedObjectsSerializer>;
|
||||
for (const method of [
|
||||
'isRawSavedObject',
|
||||
'rawToSavedObject',
|
||||
'savedObjectToRaw',
|
||||
'generateRawId',
|
||||
'generateRawLegacyUrlAliasId',
|
||||
'trimIdPrefix',
|
||||
] as Array<keyof SavedObjectsSerializer>) {
|
||||
jest.spyOn(serializer, method);
|
||||
}
|
||||
|
||||
return serializer as jest.Mocked<SavedObjectsSerializer>;
|
||||
};
|
||||
|
||||
export const createDocumentMigrator = (registry: SavedObjectTypeRegistry) => {
|
||||
|
|
|
@ -44,6 +44,7 @@ export type {
|
|||
ISavedObjectsPointInTimeFinder,
|
||||
SavedObjectsCreatePointInTimeFinderDependencies,
|
||||
SavedObjectsPitParams,
|
||||
SavedObjectsResolveOptions,
|
||||
SavedObjectsResolveResponse,
|
||||
SavedObjectsCollectMultiNamespaceReferencesObject,
|
||||
SavedObjectsUpdateObjectsSpacesResponseObject,
|
||||
|
@ -54,6 +55,7 @@ export type {
|
|||
SavedObjectsClosePointInTimeOptions,
|
||||
SavedObjectsCreatePointInTimeFinderOptions,
|
||||
SavedObjectsFindOptions,
|
||||
SavedObjectsGetOptions,
|
||||
SavedObjectsPointInTimeFinderClient,
|
||||
SavedObjectsBulkDeleteObject,
|
||||
SavedObjectsBulkDeleteOptions,
|
||||
|
|
|
@ -61,4 +61,6 @@ export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions {
|
|||
* * For global object types (registered with `namespaceType: 'agnostic'`): this option cannot be used.
|
||||
*/
|
||||
initialNamespaces?: string[];
|
||||
/** {@link SavedObjectsRawDocParseOptions.migrationVersionCompatibility} */
|
||||
migrationVersionCompatibility?: 'compatible' | 'raw';
|
||||
}
|
||||
|
|
|
@ -136,6 +136,8 @@ export interface SavedObjectsFindOptions {
|
|||
* Search against a specific Point In Time (PIT) that you've opened with {@link SavedObjectsClient.openPointInTimeForType}.
|
||||
*/
|
||||
pit?: SavedObjectsPitParams;
|
||||
/** {@link SavedObjectsRawDocParseOptions.migrationVersionCompatibility} */
|
||||
migrationVersionCompatibility?: 'compatible' | 'raw';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { SavedObjectsBaseOptions } from './base';
|
||||
|
||||
/**
|
||||
* Options for the saved objects get operation
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface SavedObjectsGetOptions extends SavedObjectsBaseOptions {
|
||||
/** {@link SavedObjectsRawDocParseOptions.migrationVersionCompatibility} */
|
||||
migrationVersionCompatibility?: 'compatible' | 'raw';
|
||||
}
|
|
@ -52,6 +52,7 @@ export type {
|
|||
SavedObjectsFindResult,
|
||||
SavedObjectsPitParams,
|
||||
} from './find';
|
||||
export type { SavedObjectsGetOptions } from './get';
|
||||
export type {
|
||||
SavedObjectsIncrementCounterField,
|
||||
SavedObjectsIncrementCounterOptions,
|
||||
|
@ -64,7 +65,7 @@ export type {
|
|||
SavedObjectsRemoveReferencesToOptions,
|
||||
SavedObjectsRemoveReferencesToResponse,
|
||||
} from './remove_references_to';
|
||||
export type { SavedObjectsResolveResponse } from './resolve';
|
||||
export type { SavedObjectsResolveOptions, SavedObjectsResolveResponse } from './resolve';
|
||||
export type { SavedObjectsUpdateResponse, SavedObjectsUpdateOptions } from './update';
|
||||
export type {
|
||||
SavedObjectsUpdateObjectsSpacesObject,
|
||||
|
|
|
@ -6,8 +6,19 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { SavedObjectsBaseOptions } from './base';
|
||||
import type { SavedObject } from '../..';
|
||||
|
||||
/**
|
||||
* Options for the saved objects get operation
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export interface SavedObjectsResolveOptions extends SavedObjectsBaseOptions {
|
||||
/** {@link SavedObjectsRawDocParseOptions.migrationVersionCompatibility} */
|
||||
migrationVersionCompatibility?: 'compatible' | 'raw';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @public
|
||||
|
|
|
@ -10,6 +10,7 @@ import type { SavedObject } from '..';
|
|||
import type {
|
||||
SavedObjectsBaseOptions,
|
||||
SavedObjectsFindOptions,
|
||||
SavedObjectsGetOptions,
|
||||
SavedObjectsClosePointInTimeOptions,
|
||||
SavedObjectsOpenPointInTimeOptions,
|
||||
SavedObjectsCreatePointInTimeFinderOptions,
|
||||
|
@ -19,6 +20,7 @@ import type {
|
|||
SavedObjectsUpdateObjectsSpacesOptions,
|
||||
SavedObjectsCollectMultiNamespaceReferencesObject,
|
||||
SavedObjectsUpdateObjectsSpacesResponse,
|
||||
SavedObjectsResolveOptions,
|
||||
SavedObjectsResolveResponse,
|
||||
ISavedObjectsPointInTimeFinder,
|
||||
SavedObjectsRemoveReferencesToOptions,
|
||||
|
@ -182,7 +184,7 @@ export interface SavedObjectsClientContract {
|
|||
* Returns an array of objects by id
|
||||
*
|
||||
* @param objects - array of objects to get (contains id, type, and optional fields)
|
||||
* @param options {@link SavedObjectsBaseOptions} - options for the bulk get operation
|
||||
* @param options {@link SavedObjectsGetOptions} - options for the bulk get operation
|
||||
* @returns the {@link SavedObjectsBulkResponse}
|
||||
* @example
|
||||
*
|
||||
|
@ -193,7 +195,7 @@ export interface SavedObjectsClientContract {
|
|||
*/
|
||||
bulkGet<T = unknown>(
|
||||
objects: SavedObjectsBulkGetObject[],
|
||||
options?: SavedObjectsBaseOptions
|
||||
options?: SavedObjectsGetOptions
|
||||
): Promise<SavedObjectsBulkResponse<T>>;
|
||||
|
||||
/**
|
||||
|
@ -201,12 +203,12 @@ export interface SavedObjectsClientContract {
|
|||
*
|
||||
* @param type - The type of the object to retrieve
|
||||
* @param id - The ID of the object to retrieve
|
||||
* @param options {@link SavedObjectsBaseOptions} - options for the get operation
|
||||
* @param options {@link SavedObjectsGetOptions} - options for the get operation
|
||||
*/
|
||||
get<T = unknown>(
|
||||
type: string,
|
||||
id: string,
|
||||
options?: SavedObjectsBaseOptions
|
||||
options?: SavedObjectsGetOptions
|
||||
): Promise<SavedObject<T>>;
|
||||
|
||||
/**
|
||||
|
@ -215,7 +217,7 @@ export interface SavedObjectsClientContract {
|
|||
* See documentation for `.resolve`.
|
||||
*
|
||||
* @param objects - an array of objects to resolve (contains id and type)
|
||||
* @param options {@link SavedObjectsBaseOptions} - options for the bulk resolve operation
|
||||
* @param options {@link SavedObjectsResolveOptions} - options for the bulk resolve operation
|
||||
* @returns the {@link SavedObjectsBulkResolveResponse}
|
||||
* @example
|
||||
*
|
||||
|
@ -230,7 +232,7 @@ export interface SavedObjectsClientContract {
|
|||
*/
|
||||
bulkResolve<T = unknown>(
|
||||
objects: SavedObjectsBulkResolveObject[],
|
||||
options?: SavedObjectsBaseOptions
|
||||
options?: SavedObjectsResolveOptions
|
||||
): Promise<SavedObjectsBulkResolveResponse<T>>;
|
||||
|
||||
/**
|
||||
|
@ -246,13 +248,13 @@ export interface SavedObjectsClientContract {
|
|||
*
|
||||
* @param type - The type of SavedObject to retrieve
|
||||
* @param id - The ID of the SavedObject to retrieve
|
||||
* @param options {@link SavedObjectsBaseOptions} - options for the resolve operation
|
||||
* @param options {@link SavedObjectsResolveOptions} - options for the resolve operation
|
||||
* @returns the {@link SavedObjectsResolveResponse}
|
||||
*/
|
||||
resolve<T = unknown>(
|
||||
type: string,
|
||||
id: string,
|
||||
options?: SavedObjectsBaseOptions
|
||||
options?: SavedObjectsResolveOptions
|
||||
): Promise<SavedObjectsResolveResponse<T>>;
|
||||
|
||||
/**
|
||||
|
|
|
@ -10,6 +10,7 @@ import type { SavedObject } from '@kbn/core-saved-objects-common';
|
|||
import type {
|
||||
SavedObjectsBaseOptions,
|
||||
SavedObjectsFindOptions,
|
||||
SavedObjectsGetOptions,
|
||||
SavedObjectsClosePointInTimeOptions,
|
||||
SavedObjectsOpenPointInTimeOptions,
|
||||
SavedObjectsCreatePointInTimeFinderOptions,
|
||||
|
@ -19,6 +20,7 @@ import type {
|
|||
SavedObjectsUpdateObjectsSpacesOptions,
|
||||
SavedObjectsCollectMultiNamespaceReferencesObject,
|
||||
SavedObjectsUpdateObjectsSpacesResponse,
|
||||
SavedObjectsResolveOptions,
|
||||
SavedObjectsResolveResponse,
|
||||
ISavedObjectsPointInTimeFinder,
|
||||
SavedObjectsRemoveReferencesToOptions,
|
||||
|
@ -78,6 +80,7 @@ export interface ISavedObjectsRepository {
|
|||
* @property {boolean} [options.overwrite=false]
|
||||
* @property {string} [options.namespace]
|
||||
* @property {array} [options.references=[]] - [{ name, type, id }]
|
||||
* @property {string} [options.migrationVersionCompatibility]
|
||||
* @returns {promise} the created saved object { id, type, version, attributes }
|
||||
*/
|
||||
create<T = unknown>(
|
||||
|
@ -93,6 +96,7 @@ export interface ISavedObjectsRepository {
|
|||
* @param {object} [options={}] {@link SavedObjectsCreateOptions} - options for the bulk create operation
|
||||
* @property {boolean} [options.overwrite=false] - overwrites existing documents
|
||||
* @property {string} [options.namespace]
|
||||
* @property {string} [options.migrationVersionCompatibility]
|
||||
* @returns {promise} - {saved_objects: [[{ id, type, version, references, attributes, error: { message } }]}
|
||||
*/
|
||||
bulkCreate<T = unknown>(
|
||||
|
@ -177,7 +181,8 @@ export interface ISavedObjectsRepository {
|
|||
* Returns an array of objects by id
|
||||
*
|
||||
* @param {array} objects - an array of objects containing id, type and optionally fields
|
||||
* @param {object} [options={}] {@link SavedObjectsBaseOptions} - options for the bulk get operation
|
||||
* @param {object} [options={}] {@link SavedObjectsGetOptions} - options for the bulk get operation
|
||||
* @property {string} [options.migrationVersionCompatibility]
|
||||
* @property {string} [options.namespace]
|
||||
* @returns {promise} - { saved_objects: [{ id, type, version, attributes }] }
|
||||
* @example
|
||||
|
@ -189,14 +194,15 @@ export interface ISavedObjectsRepository {
|
|||
*/
|
||||
bulkGet<T = unknown>(
|
||||
objects: SavedObjectsBulkGetObject[],
|
||||
options?: SavedObjectsBaseOptions
|
||||
options?: SavedObjectsGetOptions
|
||||
): Promise<SavedObjectsBulkResponse<T>>;
|
||||
|
||||
/**
|
||||
* Resolves an array of objects by id, using any legacy URL aliases if they exist
|
||||
*
|
||||
* @param {array} objects - an array of objects containing id, type
|
||||
* @param {object} [options={}] {@link SavedObjectsBaseOptions} - options for the bulk resolve operation
|
||||
* @param {object} [options={}] {@link SavedObjectsResolveOptions} - options for the bulk resolve operation
|
||||
* @property {string} [options.migrationVersionCompatibility]
|
||||
* @property {string} [options.namespace]
|
||||
* @returns {promise} - { resolved_objects: [{ saved_object, outcome }] }
|
||||
* @example
|
||||
|
@ -208,7 +214,7 @@ export interface ISavedObjectsRepository {
|
|||
*/
|
||||
bulkResolve<T = unknown>(
|
||||
objects: SavedObjectsBulkResolveObject[],
|
||||
options?: SavedObjectsBaseOptions
|
||||
options?: SavedObjectsResolveOptions
|
||||
): Promise<SavedObjectsBulkResolveResponse<T>>;
|
||||
|
||||
/**
|
||||
|
@ -216,14 +222,15 @@ export interface ISavedObjectsRepository {
|
|||
*
|
||||
* @param {string} type - the type of the object to get
|
||||
* @param {string} id - the ID of the object to get
|
||||
* @param {object} [options={}] {@link SavedObjectsBaseOptions} - options for the get operation
|
||||
* @param {object} [options={}] {@link SavedObjectsGetOptions} - options for the get operation
|
||||
* @property {string} [options.migrationVersionCompatibility]
|
||||
* @property {string} [options.namespace]
|
||||
* @returns {promise} - { id, type, version, attributes }
|
||||
*/
|
||||
get<T = unknown>(
|
||||
type: string,
|
||||
id: string,
|
||||
options?: SavedObjectsBaseOptions
|
||||
options?: SavedObjectsGetOptions
|
||||
): Promise<SavedObject<T>>;
|
||||
|
||||
/**
|
||||
|
@ -231,14 +238,15 @@ export interface ISavedObjectsRepository {
|
|||
*
|
||||
* @param {string} type - the type of the object to resolve
|
||||
* @param {string} id - the id of the object to resolve
|
||||
* @param {object} [options={}] {@link SavedObjectsBaseOptions} - options for the resolve operation
|
||||
* @param {object} [options={}] {@link SavedObjectsResolveOptions} - options for the resolve operation
|
||||
* @property {string} [options.migrationVersionCompatibility]
|
||||
* @property {string} [options.namespace]
|
||||
* @returns {promise} - { saved_object, outcome }
|
||||
*/
|
||||
resolve<T = unknown>(
|
||||
type: string,
|
||||
id: string,
|
||||
options?: SavedObjectsBaseOptions
|
||||
options?: SavedObjectsResolveOptions
|
||||
): Promise<SavedObjectsResolveResponse<T>>;
|
||||
|
||||
/**
|
||||
|
|
|
@ -104,13 +104,59 @@ describe('#rawToSavedObject', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test(`if _source.migrationVersion is unspecified it doesn't set migrationVersion`, () => {
|
||||
const actual = singleNamespaceSerializer.rawToSavedObject({
|
||||
_id: 'foo:bar',
|
||||
_source: {
|
||||
type: 'foo',
|
||||
test('derives original `migrationVersion` in compatibility mode', () => {
|
||||
const actual = singleNamespaceSerializer.rawToSavedObject(
|
||||
{
|
||||
_id: 'foo:bar',
|
||||
_source: {
|
||||
migrationVersion: { foo: '1.0.0' },
|
||||
type: 'foo',
|
||||
typeMigrationVersion: '1.2.3',
|
||||
},
|
||||
},
|
||||
});
|
||||
{ migrationVersionCompatibility: 'compatible' }
|
||||
);
|
||||
expect(actual).toHaveProperty('migrationVersion', { foo: '1.0.0' });
|
||||
});
|
||||
|
||||
test('derives `migrationVersion` in compatibility mode', () => {
|
||||
const actual = singleNamespaceSerializer.rawToSavedObject(
|
||||
{
|
||||
_id: 'foo:bar',
|
||||
_source: {
|
||||
type: 'foo',
|
||||
typeMigrationVersion: '1.2.3',
|
||||
},
|
||||
},
|
||||
{ migrationVersionCompatibility: 'compatible' }
|
||||
);
|
||||
expect(actual).toHaveProperty('migrationVersion', { foo: '1.2.3' });
|
||||
});
|
||||
|
||||
test('does not derive `migrationVersion` if there is no type version', () => {
|
||||
const actual = singleNamespaceSerializer.rawToSavedObject(
|
||||
{
|
||||
_id: 'foo:bar',
|
||||
_source: {
|
||||
type: 'foo',
|
||||
},
|
||||
},
|
||||
{ migrationVersionCompatibility: 'compatible' }
|
||||
);
|
||||
expect(actual).not.toHaveProperty('migrationVersion');
|
||||
});
|
||||
|
||||
test('does not derive `migrationVersion` in raw mode', () => {
|
||||
const actual = singleNamespaceSerializer.rawToSavedObject(
|
||||
{
|
||||
_id: 'foo:bar',
|
||||
_source: {
|
||||
type: 'foo',
|
||||
typeMigrationVersion: '1.2.3',
|
||||
},
|
||||
},
|
||||
{ migrationVersionCompatibility: 'raw' }
|
||||
);
|
||||
expect(actual).not.toHaveProperty('migrationVersion');
|
||||
});
|
||||
|
||||
|
|
|
@ -85,16 +85,18 @@ export class SavedObjectsSerializer implements ISavedObjectsSerializer {
|
|||
): SavedObjectSanitizedDoc<T> {
|
||||
this.checkIsRawSavedObject(doc, options); // throws a descriptive error if the document is not a saved object
|
||||
|
||||
const { namespaceTreatment = 'strict' } = options;
|
||||
const { namespaceTreatment = 'strict', migrationVersionCompatibility = 'raw' } = options;
|
||||
const { _id, _source, _seq_no, _primary_term } = doc;
|
||||
const {
|
||||
type,
|
||||
namespaces,
|
||||
originId,
|
||||
migrationVersion,
|
||||
references,
|
||||
coreMigrationVersion,
|
||||
typeMigrationVersion,
|
||||
migrationVersion = migrationVersionCompatibility === 'compatible' && typeMigrationVersion
|
||||
? { [type]: typeMigrationVersion }
|
||||
: undefined,
|
||||
} = _source;
|
||||
|
||||
const version =
|
||||
|
|
|
@ -76,7 +76,10 @@ export const registerBulkCreateRoute = (
|
|||
if (!allowHttpApiAccess) {
|
||||
throwIfAnyTypeNotVisibleByAPI(typesToCheck, savedObjects.typeRegistry);
|
||||
}
|
||||
const result = await savedObjects.client.bulkCreate(req.body, { overwrite });
|
||||
const result = await savedObjects.client.bulkCreate(req.body, {
|
||||
overwrite,
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
return res.ok({ body: result });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -57,7 +57,9 @@ export const registerBulkGetRoute = (
|
|||
if (!allowHttpApiAccess) {
|
||||
throwIfAnyTypeNotVisibleByAPI(typesToCheck, savedObjects.typeRegistry);
|
||||
}
|
||||
const result = await savedObjects.client.bulkGet(req.body);
|
||||
const result = await savedObjects.client.bulkGet(req.body, {
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
return res.ok({ body: result });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -55,7 +55,9 @@ export const registerBulkResolveRoute = (
|
|||
if (!allowHttpApiAccess) {
|
||||
throwIfAnyTypeNotVisibleByAPI(typesToCheck, savedObjects.typeRegistry);
|
||||
}
|
||||
const result = await savedObjects.client.bulkResolve(req.body);
|
||||
const result = await savedObjects.client.bulkResolve(req.body, {
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
return res.ok({ body: result });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -90,6 +90,7 @@ export const registerCreateRoute = (
|
|||
typeMigrationVersion,
|
||||
references,
|
||||
initialNamespaces,
|
||||
migrationVersionCompatibility: 'compatible' as const,
|
||||
};
|
||||
const result = await savedObjects.client.create(type, attributes, options);
|
||||
return res.ok({ body: result });
|
||||
|
|
|
@ -123,6 +123,7 @@ export const registerFindRoute = (
|
|||
filter: query.filter,
|
||||
aggs,
|
||||
namespaces,
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
|
||||
return res.ok({ body: result });
|
||||
|
|
|
@ -56,7 +56,9 @@ export const registerGetRoute = (
|
|||
throwIfTypeNotVisibleByAPI(type, savedObjects.typeRegistry);
|
||||
}
|
||||
|
||||
const object = await savedObjects.client.get(type, id);
|
||||
const object = await savedObjects.client.get(type, id, {
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
return res.ok({ body: object });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -49,7 +49,9 @@ export const registerResolveRoute = (
|
|||
if (!allowHttpApiAccess) {
|
||||
throwIfTypeNotVisibleByAPI(type, savedObjects.typeRegistry);
|
||||
}
|
||||
const result = await savedObjects.client.resolve(type, id);
|
||||
const result = await savedObjects.client.resolve(type, id, {
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
return res.ok({ body: result });
|
||||
})
|
||||
);
|
||||
|
|
|
@ -143,4 +143,12 @@ export interface SavedObjectsRawDocParseOptions {
|
|||
* If not specified, the default treatment is `strict`.
|
||||
*/
|
||||
namespaceTreatment?: 'strict' | 'lax';
|
||||
|
||||
/**
|
||||
* Optional setting to allow compatible handling of the `migrationVersion` field.
|
||||
* This is needed to return the `migrationVersion` field in the same format as it was before migrating to the `typeMigrationVersion` property.
|
||||
*
|
||||
* @default 'raw'
|
||||
*/
|
||||
migrationVersionCompatibility?: 'compatible' | 'raw';
|
||||
}
|
||||
|
|
|
@ -79,9 +79,10 @@ describe('POST /api/saved_objects/_bulk_create with allowApiAccess true', () =>
|
|||
.expect(200);
|
||||
|
||||
expect(savedObjectsClient.bulkCreate).toHaveBeenCalledTimes(1);
|
||||
|
||||
const args = savedObjectsClient.bulkCreate.mock.calls[0];
|
||||
expect(args[1]).toEqual({ overwrite: true });
|
||||
expect(savedObjectsClient.bulkCreate).nthCalledWith(1, expect.anything(), {
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
overwrite: true,
|
||||
});
|
||||
const result = await supertest(httpSetup.server.listener)
|
||||
.post('/api/saved_objects/_bulk_create')
|
||||
.send([
|
||||
|
|
|
@ -148,8 +148,8 @@ describe('POST /api/saved_objects/_bulk_create', () => {
|
|||
.expect(200);
|
||||
|
||||
expect(savedObjectsClient.bulkCreate).toHaveBeenCalledTimes(1);
|
||||
const args = savedObjectsClient.bulkCreate.mock.calls[0];
|
||||
expect(args[1]).toEqual({ overwrite: true });
|
||||
const [[, options]] = savedObjectsClient.bulkCreate.mock.calls;
|
||||
expect(options).toEqual({ migrationVersionCompatibility: 'compatible', overwrite: true });
|
||||
});
|
||||
|
||||
it('returns with status 400 when a type is hidden from the HTTP APIs', async () => {
|
||||
|
|
|
@ -112,7 +112,9 @@ describe('POST /api/saved_objects/_bulk_get', () => {
|
|||
.expect(200);
|
||||
|
||||
expect(savedObjectsClient.bulkGet).toHaveBeenCalledTimes(1);
|
||||
expect(savedObjectsClient.bulkGet).toHaveBeenCalledWith(docs);
|
||||
expect(savedObjectsClient.bulkGet).toHaveBeenCalledWith(docs, {
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns with status 400 when a type is hidden from the HTTP APIs', async () => {
|
||||
|
|
|
@ -116,7 +116,9 @@ describe('POST /api/saved_objects/_bulk_resolve', () => {
|
|||
.expect(200);
|
||||
|
||||
expect(savedObjectsClient.bulkResolve).toHaveBeenCalledTimes(1);
|
||||
expect(savedObjectsClient.bulkResolve).toHaveBeenCalledWith(docs);
|
||||
expect(savedObjectsClient.bulkResolve).toHaveBeenCalledWith(docs, {
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns with status 400 when a type is hidden from the HTTP APIs', async () => {
|
||||
|
|
|
@ -115,7 +115,12 @@ describe('POST /api/saved_objects/{type}', () => {
|
|||
expect(savedObjectsClient.create).toHaveBeenCalledWith(
|
||||
'index-pattern',
|
||||
{ title: 'Testing' },
|
||||
{ overwrite: false, id: undefined, migrationVersion: undefined }
|
||||
{
|
||||
overwrite: false,
|
||||
id: undefined,
|
||||
migrationVersion: undefined,
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -135,7 +140,7 @@ describe('POST /api/saved_objects/{type}', () => {
|
|||
expect(args).toEqual([
|
||||
'index-pattern',
|
||||
{ title: 'Testing' },
|
||||
{ overwrite: false, id: 'logstash-*' },
|
||||
{ overwrite: false, id: 'logstash-*', migrationVersionCompatibility: 'compatible' },
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
@ -176,6 +176,7 @@ describe('GET /api/saved_objects/_find', () => {
|
|||
defaultSearchOperator: 'OR',
|
||||
hasReferenceOperator: 'OR',
|
||||
hasNoReferenceOperator: 'OR',
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -186,7 +187,7 @@ describe('GET /api/saved_objects/_find', () => {
|
|||
|
||||
expect(savedObjectsClient.find).toHaveBeenCalledTimes(1);
|
||||
|
||||
const options = savedObjectsClient.find.mock.calls[0][0];
|
||||
const [[options]] = savedObjectsClient.find.mock.calls;
|
||||
expect(options).toEqual(expect.objectContaining({ perPage: 10, page: 50 }));
|
||||
});
|
||||
|
||||
|
|
|
@ -118,9 +118,9 @@ describe('GET /api/saved_objects/{type}/{id}', () => {
|
|||
.expect(200);
|
||||
|
||||
expect(savedObjectsClient.get).toHaveBeenCalled();
|
||||
|
||||
const args = savedObjectsClient.get.mock.calls[0];
|
||||
expect(args).toEqual(['index-pattern', 'logstash-*']);
|
||||
expect(savedObjectsClient.get).nthCalledWith(1, 'index-pattern', 'logstash-*', {
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns with status 400 when a type is hidden from the http APIs', async () => {
|
||||
|
|
|
@ -118,9 +118,9 @@ describe('GET /api/saved_objects/resolve/{type}/{id}', () => {
|
|||
.expect(200);
|
||||
|
||||
expect(savedObjectsClient.resolve).toHaveBeenCalled();
|
||||
|
||||
const args = savedObjectsClient.resolve.mock.calls[0];
|
||||
expect(args).toEqual(['index-pattern', 'logstash-*']);
|
||||
expect(savedObjectsClient.resolve).nthCalledWith(1, 'index-pattern', 'logstash-*', {
|
||||
migrationVersionCompatibility: 'compatible',
|
||||
});
|
||||
});
|
||||
|
||||
it('returns with status 400 is a type is hidden from the HTTP APIs', async () => {
|
||||
|
|
|
@ -70,6 +70,9 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
attributes: {
|
||||
title: 'A great new dashboard',
|
||||
},
|
||||
migrationVersion: {
|
||||
dashboard: resp.body.saved_objects[1].migrationVersion.dashboard,
|
||||
},
|
||||
coreMigrationVersion: '8.8.0',
|
||||
typeMigrationVersion: resp.body.saved_objects[1].typeMigrationVersion,
|
||||
references: [],
|
||||
|
|
|
@ -71,6 +71,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
kibanaSavedObjectMeta:
|
||||
resp.body.saved_objects[0].attributes.kibanaSavedObjectMeta,
|
||||
},
|
||||
migrationVersion: resp.body.saved_objects[0].migrationVersion,
|
||||
coreMigrationVersion: '8.8.0',
|
||||
typeMigrationVersion: resp.body.saved_objects[0].typeMigrationVersion,
|
||||
namespaces: ['default'],
|
||||
|
@ -102,12 +103,14 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
defaultIndex: '91200a00-9efd-11e7-acb3-3dab96693fab',
|
||||
},
|
||||
namespaces: ['default'],
|
||||
migrationVersion: resp.body.saved_objects[2].migrationVersion,
|
||||
coreMigrationVersion: '8.8.0',
|
||||
typeMigrationVersion: resp.body.saved_objects[2].typeMigrationVersion,
|
||||
references: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
expect(resp.body.saved_objects[0].migrationVersion).to.be.ok();
|
||||
expect(resp.body.saved_objects[0].typeMigrationVersion).to.be.ok();
|
||||
}));
|
||||
});
|
||||
|
|
|
@ -49,6 +49,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
expect(resp.body).to.eql({
|
||||
id: resp.body.id,
|
||||
type: 'visualization',
|
||||
migrationVersion: resp.body.migrationVersion,
|
||||
coreMigrationVersion: '8.8.0',
|
||||
typeMigrationVersion: resp.body.typeMigrationVersion,
|
||||
updated_at: resp.body.updated_at,
|
||||
|
@ -60,6 +61,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
references: [],
|
||||
namespaces: ['default'],
|
||||
});
|
||||
expect(resp.body.migrationVersion).to.be.ok();
|
||||
expect(resp.body.typeMigrationVersion).to.be.ok();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -48,6 +48,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
expect(resp.body.saved_objects.map((so: { id: string }) => so.id)).to.eql([
|
||||
'dd7caf20-9efd-11e7-acb3-3dab96693fab',
|
||||
]);
|
||||
expect(resp.body.saved_objects[0].migrationVersion).to.be.ok();
|
||||
expect(resp.body.saved_objects[0].typeMigrationVersion).to.be.ok();
|
||||
}));
|
||||
|
||||
|
@ -124,6 +125,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
namespaces: so.namespaces,
|
||||
}))
|
||||
).to.eql([{ id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', namespaces: [SPACE_ID] }]);
|
||||
expect(resp.body.saved_objects[0].migrationVersion).to.be.ok();
|
||||
expect(resp.body.saved_objects[0].typeMigrationVersion).to.be.ok();
|
||||
}));
|
||||
});
|
||||
|
|
|
@ -36,6 +36,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
updated_at: resp.body.updated_at,
|
||||
created_at: resp.body.created_at,
|
||||
version: resp.body.version,
|
||||
migrationVersion: resp.body.migrationVersion,
|
||||
coreMigrationVersion: '8.8.0',
|
||||
typeMigrationVersion: resp.body.typeMigrationVersion,
|
||||
attributes: {
|
||||
|
@ -56,6 +57,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
],
|
||||
namespaces: ['default'],
|
||||
});
|
||||
expect(resp.body.migrationVersion).to.be.ok();
|
||||
expect(resp.body.typeMigrationVersion).to.be.ok();
|
||||
}));
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
updated_at: '2015-01-01T00:00:00.000Z',
|
||||
created_at: '2015-01-01T00:00:00.000Z',
|
||||
version: resp.body.saved_object.version,
|
||||
migrationVersion: resp.body.saved_object.migrationVersion,
|
||||
coreMigrationVersion: '8.8.0',
|
||||
typeMigrationVersion: resp.body.saved_object.typeMigrationVersion,
|
||||
attributes: {
|
||||
|
@ -63,6 +64,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
},
|
||||
outcome: 'exactMatch',
|
||||
});
|
||||
expect(resp.body.saved_object.migrationVersion).to.be.ok();
|
||||
expect(resp.body.saved_object.typeMigrationVersion).to.be.ok();
|
||||
}));
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue