From 13c4ec45dcfc98df821379a94783a69db5b8aed9 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Mon, 17 Aug 2020 12:20:46 +0100 Subject: [PATCH 01/10] added version to saved object creation --- ...-plugin-core-server.savedobjectscreateoptions.md | 1 + ...core-server.savedobjectscreateoptions.version.md | 13 +++++++++++++ .../saved_objects/service/lib/repository.test.js | 10 ++++++++++ .../server/saved_objects/service/lib/repository.ts | 2 ++ .../saved_objects/service/saved_objects_client.ts | 5 +++++ src/core/server/server.api.md | 1 + 6 files changed, 32 insertions(+) create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.version.md diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.md index 5e9433c5c9196..c5201efd0608d 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.md @@ -20,4 +20,5 @@ export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions | [overwrite](./kibana-plugin-core-server.savedobjectscreateoptions.overwrite.md) | boolean | Overwrite existing documents (defaults to false) | | [references](./kibana-plugin-core-server.savedobjectscreateoptions.references.md) | SavedObjectReference[] | | | [refresh](./kibana-plugin-core-server.savedobjectscreateoptions.refresh.md) | MutatingOperationRefreshSetting | The Elasticsearch Refresh setting for this operation | +| [version](./kibana-plugin-core-server.savedobjectscreateoptions.version.md) | string | An opaque version number which changes on each successful write operation. Can be used in conjunction with overwrite for implementing optimistic concurrency control. | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.version.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.version.md new file mode 100644 index 0000000000000..51da57064abb9 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectscreateoptions.version.md @@ -0,0 +1,13 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsCreateOptions](./kibana-plugin-core-server.savedobjectscreateoptions.md) > [version](./kibana-plugin-core-server.savedobjectscreateoptions.version.md) + +## SavedObjectsCreateOptions.version property + +An opaque version number which changes on each successful write operation. Can be used in conjunction with `overwrite` for implementing optimistic concurrency control. + +Signature: + +```typescript +version?: string; +``` diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 4a9fceb9bf357..5632b5deaa816 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -1516,6 +1516,16 @@ describe('SavedObjectsRepository', () => { expect(client.index).toHaveBeenCalled(); }); + it(`should use the ES index with version of ID and version are defined and overwrite=true`, async () => { + await createSuccess(type, attributes, { id, overwrite: true, version: mockVersion }); + expect(client.index).toHaveBeenCalled(); + + expect(client.index.mock.calls[0][0]).toMatchObject({ + if_seq_no: mockVersionProps._seq_no, + if_primary_term: mockVersionProps._primary_term, + }); + }); + it(`should use the ES create action if ID is defined and overwrite=false`, async () => { await createSuccess(type, attributes, { id }); expect(client.create).toHaveBeenCalled(); diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index d7e1ecba0370b..226caecccf931 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -220,6 +220,7 @@ export class SavedObjectsRepository { overwrite = false, references = [], refresh = DEFAULT_REFRESH_SETTING, + version, } = options; if (!this._allowedTypes.includes(type)) { @@ -259,6 +260,7 @@ export class SavedObjectsRepository { index: this.getIndexForType(type), refresh, body: raw._source, + ...(overwrite && version ? decodeRequestVersion(version) : {}), }; const { body } = diff --git a/src/core/server/saved_objects/service/saved_objects_client.ts b/src/core/server/saved_objects/service/saved_objects_client.ts index e15a92c92772f..f5a0455ccad5b 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.ts @@ -37,6 +37,11 @@ export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions { id?: string; /** Overwrite existing documents (defaults to false) */ overwrite?: boolean; + /** + * An opaque version number which changes on each successful write operation. + * Can be used in conjunction with `overwrite` for implementing optimistic concurrency control. + **/ + version?: string; /** {@inheritDoc SavedObjectsMigrationVersion} */ migrationVersion?: SavedObjectsMigrationVersion; references?: SavedObjectReference[]; diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 21ef66230f698..429c22dff8788 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2173,6 +2173,7 @@ export interface SavedObjectsCreateOptions extends SavedObjectsBaseOptions { // (undocumented) references?: SavedObjectReference[]; refresh?: MutatingOperationRefreshSetting; + version?: string; } // @public (undocumented) From d4820e1fd5d3073b23cc007b32ed5bd14a59c470 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Mon, 17 Aug 2020 16:08:47 +0100 Subject: [PATCH 02/10] added version to saved object bulk creation --- .../service/lib/repository.test.js | 33 +++++++++++++++++-- .../saved_objects/service/lib/repository.ts | 10 +++++- .../service/saved_objects_client.ts | 1 + 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 5632b5deaa816..c461fbacc51ca 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -464,8 +464,16 @@ describe('SavedObjectsRepository', () => { { method, _index = expect.any(String), getId = () => expect.any(String) } ) => { const body = []; - for (const { type, id } of objects) { - body.push({ [method]: { _index, _id: getId(type, id) } }); + for (const { type, id, if_primary_term: ifPrimaryTerm, if_seq_no: ifSeqNo } of objects) { + body.push({ + [method]: { + _index, + _id: getId(type, id), + ...(ifPrimaryTerm && ifSeqNo + ? { if_primary_term: expect.any(Number), if_seq_no: expect.any(Number) } + : {}), + }, + }); body.push(expect.any(Object)); } expect(client.bulk).toHaveBeenCalledWith( @@ -525,6 +533,27 @@ describe('SavedObjectsRepository', () => { expectClientCallArgsAction([obj1, obj2], { method: 'index' }); }); + it(`should use the ES index method with version if ID and version are defined and overwrite=true`, async () => { + await bulkCreateSuccess( + [ + { + ...obj1, + version: mockVersion, + }, + obj2, + ], + { overwrite: true } + ); + + const obj1WithSeq = { + ...obj1, + if_seq_no: mockVersionProps._seq_no, + if_primary_term: mockVersionProps._primary_term, + }; + + expectClientCallArgsAction([obj1WithSeq, obj2], { method: 'index' }); + }); + it(`should use the ES create method if ID is defined and overwrite=false`, async () => { await bulkCreateSuccess([obj1, obj2]); expectClientCallArgsAction([obj1, obj2], { method: 'create' }); diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 226caecccf931..9f6db446ea195 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -347,7 +347,12 @@ export class SavedObjectsRepository { let savedObjectNamespace; let savedObjectNamespaces; - const { esRequestIndex, object, method } = expectedBulkGetResult.value; + let versionProperties; + const { + esRequestIndex, + object: { version, ...object }, + method, + } = expectedBulkGetResult.value; if (esRequestIndex !== undefined) { const indexFound = bulkGetResponse?.statusCode !== 404; const actualResult = indexFound ? bulkGetResponse?.body.docs[esRequestIndex] : undefined; @@ -364,12 +369,14 @@ export class SavedObjectsRepository { }; } savedObjectNamespaces = getSavedObjectNamespaces(namespace, docFound && actualResult); + versionProperties = getExpectedVersionProperties(version, actualResult); } else { if (this._registry.isSingleNamespace(object.type)) { savedObjectNamespace = namespace; } else if (this._registry.isMultiNamespace(object.type)) { savedObjectNamespaces = getSavedObjectNamespaces(namespace); } + versionProperties = getExpectedVersionProperties(version); } const expectedResult = { @@ -394,6 +401,7 @@ export class SavedObjectsRepository { [method]: { _id: expectedResult.rawMigratedDoc._id, _index: this.getIndexForType(object.type), + ...(overwrite && versionProperties), }, }, expectedResult.rawMigratedDoc._source diff --git a/src/core/server/saved_objects/service/saved_objects_client.ts b/src/core/server/saved_objects/service/saved_objects_client.ts index f5a0455ccad5b..6a9f4f5143e84 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.ts @@ -57,6 +57,7 @@ export interface SavedObjectsBulkCreateObject { id?: string; type: string; attributes: T; + version?: string; references?: SavedObjectReference[]; /** {@inheritDoc SavedObjectsMigrationVersion} */ migrationVersion?: SavedObjectsMigrationVersion; From 814b98ddc9dbb931c7c2fe7080c8610bdeec949e Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Mon, 17 Aug 2020 18:59:29 +0100 Subject: [PATCH 03/10] added missing core docs --- ...plugin-core-server.savedobjectsbulkcreateobject.md | 1 + ...ore-server.savedobjectsbulkcreateobject.version.md | 11 +++++++++++ src/core/server/server.api.md | 2 ++ .../server/services/epm/kibana/assets/install.ts | 4 +++- 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md index 5a9ca36ba56f4..5ccad134248f6 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md @@ -20,4 +20,5 @@ export interface SavedObjectsBulkCreateObject | [migrationVersion](./kibana-plugin-core-server.savedobjectsbulkcreateobject.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | | [references](./kibana-plugin-core-server.savedobjectsbulkcreateobject.references.md) | SavedObjectReference[] | | | [type](./kibana-plugin-core-server.savedobjectsbulkcreateobject.type.md) | string | | +| [version](./kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md) | string | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md new file mode 100644 index 0000000000000..ca2a38693d036 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-core-server.savedobjectsbulkcreateobject.md) > [version](./kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md) + +## SavedObjectsBulkCreateObject.version property + +Signature: + +```typescript +version?: string; +``` diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 429c22dff8788..7734dacee87c7 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2039,6 +2039,8 @@ export interface SavedObjectsBulkCreateObject { references?: SavedObjectReference[]; // (undocumented) type: string; + // (undocumented) + version?: string; } // @public (undocumented) diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts index 5741764164b83..84892d2027847 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts @@ -14,7 +14,9 @@ import * as Registry from '../../registry'; import { AssetType, KibanaAssetType, AssetReference } from '../../../../types'; import { savedObjectTypes } from '../../packages'; -type SavedObjectToBe = Required & { type: AssetType }; +type SavedObjectToBe = Required> & { + type: AssetType; +}; export type ArchiveAsset = Pick< SavedObject, 'id' | 'attributes' | 'migrationVersion' | 'references' From 7bd360cca060e1007455434bbc88ec6f511d45e8 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Tue, 18 Aug 2020 11:06:03 +0100 Subject: [PATCH 04/10] Revert "added missing core docs" This reverts commit 814b98ddc9dbb931c7c2fe7080c8610bdeec949e. --- ...plugin-core-server.savedobjectsbulkcreateobject.md | 1 - ...ore-server.savedobjectsbulkcreateobject.version.md | 11 ----------- src/core/server/server.api.md | 2 -- .../server/services/epm/kibana/assets/install.ts | 4 +--- 4 files changed, 1 insertion(+), 17 deletions(-) delete mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md index 5ccad134248f6..5a9ca36ba56f4 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md @@ -20,5 +20,4 @@ export interface SavedObjectsBulkCreateObject | [migrationVersion](./kibana-plugin-core-server.savedobjectsbulkcreateobject.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | | [references](./kibana-plugin-core-server.savedobjectsbulkcreateobject.references.md) | SavedObjectReference[] | | | [type](./kibana-plugin-core-server.savedobjectsbulkcreateobject.type.md) | string | | -| [version](./kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md) | string | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md deleted file mode 100644 index ca2a38693d036..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md +++ /dev/null @@ -1,11 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-core-server.savedobjectsbulkcreateobject.md) > [version](./kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md) - -## SavedObjectsBulkCreateObject.version property - -Signature: - -```typescript -version?: string; -``` diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index d7f1e463a07e4..c7ba03f4da2ba 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2041,8 +2041,6 @@ export interface SavedObjectsBulkCreateObject { references?: SavedObjectReference[]; // (undocumented) type: string; - // (undocumented) - version?: string; } // @public (undocumented) diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts index 84892d2027847..5741764164b83 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts @@ -14,9 +14,7 @@ import * as Registry from '../../registry'; import { AssetType, KibanaAssetType, AssetReference } from '../../../../types'; import { savedObjectTypes } from '../../packages'; -type SavedObjectToBe = Required> & { - type: AssetType; -}; +type SavedObjectToBe = Required & { type: AssetType }; export type ArchiveAsset = Pick< SavedObject, 'id' | 'attributes' | 'migrationVersion' | 'references' From caa1834b3d732ba9983f83cfad113700a6f411c6 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Tue, 18 Aug 2020 11:06:15 +0100 Subject: [PATCH 05/10] Revert "added version to saved object bulk creation" This reverts commit d4820e1fd5d3073b23cc007b32ed5bd14a59c470. --- .../service/lib/repository.test.js | 33 ++----------------- .../saved_objects/service/lib/repository.ts | 10 +----- .../service/saved_objects_client.ts | 1 - 3 files changed, 3 insertions(+), 41 deletions(-) diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index c461fbacc51ca..5632b5deaa816 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -464,16 +464,8 @@ describe('SavedObjectsRepository', () => { { method, _index = expect.any(String), getId = () => expect.any(String) } ) => { const body = []; - for (const { type, id, if_primary_term: ifPrimaryTerm, if_seq_no: ifSeqNo } of objects) { - body.push({ - [method]: { - _index, - _id: getId(type, id), - ...(ifPrimaryTerm && ifSeqNo - ? { if_primary_term: expect.any(Number), if_seq_no: expect.any(Number) } - : {}), - }, - }); + for (const { type, id } of objects) { + body.push({ [method]: { _index, _id: getId(type, id) } }); body.push(expect.any(Object)); } expect(client.bulk).toHaveBeenCalledWith( @@ -533,27 +525,6 @@ describe('SavedObjectsRepository', () => { expectClientCallArgsAction([obj1, obj2], { method: 'index' }); }); - it(`should use the ES index method with version if ID and version are defined and overwrite=true`, async () => { - await bulkCreateSuccess( - [ - { - ...obj1, - version: mockVersion, - }, - obj2, - ], - { overwrite: true } - ); - - const obj1WithSeq = { - ...obj1, - if_seq_no: mockVersionProps._seq_no, - if_primary_term: mockVersionProps._primary_term, - }; - - expectClientCallArgsAction([obj1WithSeq, obj2], { method: 'index' }); - }); - it(`should use the ES create method if ID is defined and overwrite=false`, async () => { await bulkCreateSuccess([obj1, obj2]); expectClientCallArgsAction([obj1, obj2], { method: 'create' }); diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 9f6db446ea195..226caecccf931 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -347,12 +347,7 @@ export class SavedObjectsRepository { let savedObjectNamespace; let savedObjectNamespaces; - let versionProperties; - const { - esRequestIndex, - object: { version, ...object }, - method, - } = expectedBulkGetResult.value; + const { esRequestIndex, object, method } = expectedBulkGetResult.value; if (esRequestIndex !== undefined) { const indexFound = bulkGetResponse?.statusCode !== 404; const actualResult = indexFound ? bulkGetResponse?.body.docs[esRequestIndex] : undefined; @@ -369,14 +364,12 @@ export class SavedObjectsRepository { }; } savedObjectNamespaces = getSavedObjectNamespaces(namespace, docFound && actualResult); - versionProperties = getExpectedVersionProperties(version, actualResult); } else { if (this._registry.isSingleNamespace(object.type)) { savedObjectNamespace = namespace; } else if (this._registry.isMultiNamespace(object.type)) { savedObjectNamespaces = getSavedObjectNamespaces(namespace); } - versionProperties = getExpectedVersionProperties(version); } const expectedResult = { @@ -401,7 +394,6 @@ export class SavedObjectsRepository { [method]: { _id: expectedResult.rawMigratedDoc._id, _index: this.getIndexForType(object.type), - ...(overwrite && versionProperties), }, }, expectedResult.rawMigratedDoc._source diff --git a/src/core/server/saved_objects/service/saved_objects_client.ts b/src/core/server/saved_objects/service/saved_objects_client.ts index 6a9f4f5143e84..f5a0455ccad5b 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.ts @@ -57,7 +57,6 @@ export interface SavedObjectsBulkCreateObject { id?: string; type: string; attributes: T; - version?: string; references?: SavedObjectReference[]; /** {@inheritDoc SavedObjectsMigrationVersion} */ migrationVersion?: SavedObjectsMigrationVersion; From 8f3dfc86623728a37860aca5021916c2e8be8acd Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Tue, 18 Aug 2020 15:39:39 +0100 Subject: [PATCH 06/10] Revert "Revert "added version to saved object bulk creation"" This reverts commit caa1834b3d732ba9983f83cfad113700a6f411c6. --- .../service/lib/repository.test.js | 33 +++++++++++++++++-- .../saved_objects/service/lib/repository.ts | 10 +++++- .../service/saved_objects_client.ts | 1 + 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 5632b5deaa816..c461fbacc51ca 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -464,8 +464,16 @@ describe('SavedObjectsRepository', () => { { method, _index = expect.any(String), getId = () => expect.any(String) } ) => { const body = []; - for (const { type, id } of objects) { - body.push({ [method]: { _index, _id: getId(type, id) } }); + for (const { type, id, if_primary_term: ifPrimaryTerm, if_seq_no: ifSeqNo } of objects) { + body.push({ + [method]: { + _index, + _id: getId(type, id), + ...(ifPrimaryTerm && ifSeqNo + ? { if_primary_term: expect.any(Number), if_seq_no: expect.any(Number) } + : {}), + }, + }); body.push(expect.any(Object)); } expect(client.bulk).toHaveBeenCalledWith( @@ -525,6 +533,27 @@ describe('SavedObjectsRepository', () => { expectClientCallArgsAction([obj1, obj2], { method: 'index' }); }); + it(`should use the ES index method with version if ID and version are defined and overwrite=true`, async () => { + await bulkCreateSuccess( + [ + { + ...obj1, + version: mockVersion, + }, + obj2, + ], + { overwrite: true } + ); + + const obj1WithSeq = { + ...obj1, + if_seq_no: mockVersionProps._seq_no, + if_primary_term: mockVersionProps._primary_term, + }; + + expectClientCallArgsAction([obj1WithSeq, obj2], { method: 'index' }); + }); + it(`should use the ES create method if ID is defined and overwrite=false`, async () => { await bulkCreateSuccess([obj1, obj2]); expectClientCallArgsAction([obj1, obj2], { method: 'create' }); diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 226caecccf931..9f6db446ea195 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -347,7 +347,12 @@ export class SavedObjectsRepository { let savedObjectNamespace; let savedObjectNamespaces; - const { esRequestIndex, object, method } = expectedBulkGetResult.value; + let versionProperties; + const { + esRequestIndex, + object: { version, ...object }, + method, + } = expectedBulkGetResult.value; if (esRequestIndex !== undefined) { const indexFound = bulkGetResponse?.statusCode !== 404; const actualResult = indexFound ? bulkGetResponse?.body.docs[esRequestIndex] : undefined; @@ -364,12 +369,14 @@ export class SavedObjectsRepository { }; } savedObjectNamespaces = getSavedObjectNamespaces(namespace, docFound && actualResult); + versionProperties = getExpectedVersionProperties(version, actualResult); } else { if (this._registry.isSingleNamespace(object.type)) { savedObjectNamespace = namespace; } else if (this._registry.isMultiNamespace(object.type)) { savedObjectNamespaces = getSavedObjectNamespaces(namespace); } + versionProperties = getExpectedVersionProperties(version); } const expectedResult = { @@ -394,6 +401,7 @@ export class SavedObjectsRepository { [method]: { _id: expectedResult.rawMigratedDoc._id, _index: this.getIndexForType(object.type), + ...(overwrite && versionProperties), }, }, expectedResult.rawMigratedDoc._source diff --git a/src/core/server/saved_objects/service/saved_objects_client.ts b/src/core/server/saved_objects/service/saved_objects_client.ts index f5a0455ccad5b..6a9f4f5143e84 100644 --- a/src/core/server/saved_objects/service/saved_objects_client.ts +++ b/src/core/server/saved_objects/service/saved_objects_client.ts @@ -57,6 +57,7 @@ export interface SavedObjectsBulkCreateObject { id?: string; type: string; attributes: T; + version?: string; references?: SavedObjectReference[]; /** {@inheritDoc SavedObjectsMigrationVersion} */ migrationVersion?: SavedObjectsMigrationVersion; From c4e8c59302c43ad5a9106fd07226d37f53900d11 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Tue, 18 Aug 2020 15:39:56 +0100 Subject: [PATCH 07/10] Revert "Revert "added missing core docs"" This reverts commit 7bd360cca060e1007455434bbc88ec6f511d45e8. --- ...plugin-core-server.savedobjectsbulkcreateobject.md | 1 + ...ore-server.savedobjectsbulkcreateobject.version.md | 11 +++++++++++ src/core/server/server.api.md | 2 ++ .../server/services/epm/kibana/assets/install.ts | 4 +++- 4 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md index 5a9ca36ba56f4..5ccad134248f6 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.md @@ -20,4 +20,5 @@ export interface SavedObjectsBulkCreateObject | [migrationVersion](./kibana-plugin-core-server.savedobjectsbulkcreateobject.migrationversion.md) | SavedObjectsMigrationVersion | Information about the migrations that have been applied to this SavedObject. When Kibana starts up, KibanaMigrator detects outdated documents and migrates them based on this value. For each migration that has been applied, the plugin's name is used as a key and the latest migration version as the value. | | [references](./kibana-plugin-core-server.savedobjectsbulkcreateobject.references.md) | SavedObjectReference[] | | | [type](./kibana-plugin-core-server.savedobjectsbulkcreateobject.type.md) | string | | +| [version](./kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md) | string | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md new file mode 100644 index 0000000000000..ca2a38693d036 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsBulkCreateObject](./kibana-plugin-core-server.savedobjectsbulkcreateobject.md) > [version](./kibana-plugin-core-server.savedobjectsbulkcreateobject.version.md) + +## SavedObjectsBulkCreateObject.version property + +Signature: + +```typescript +version?: string; +``` diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index c7ba03f4da2ba..d7f1e463a07e4 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -2041,6 +2041,8 @@ export interface SavedObjectsBulkCreateObject { references?: SavedObjectReference[]; // (undocumented) type: string; + // (undocumented) + version?: string; } // @public (undocumented) diff --git a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts index 5741764164b83..84892d2027847 100644 --- a/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts +++ b/x-pack/plugins/ingest_manager/server/services/epm/kibana/assets/install.ts @@ -14,7 +14,9 @@ import * as Registry from '../../registry'; import { AssetType, KibanaAssetType, AssetReference } from '../../../../types'; import { savedObjectTypes } from '../../packages'; -type SavedObjectToBe = Required & { type: AssetType }; +type SavedObjectToBe = Required> & { + type: AssetType; +}; export type ArchiveAsset = Pick< SavedObject, 'id' | 'attributes' | 'migrationVersion' | 'references' From c391446410b769746c6d4a62cb81d538d3533835 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Tue, 18 Aug 2020 18:04:45 +0100 Subject: [PATCH 08/10] omit version from SO import/export --- .../saved_objects/import/import_saved_objects.ts | 7 ++++++- .../saved_objects/import/resolve_import_errors.ts | 12 ++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/core/server/saved_objects/import/import_saved_objects.ts b/src/core/server/saved_objects/import/import_saved_objects.ts index 6065e03fb1628..4956491a79aa9 100644 --- a/src/core/server/saved_objects/import/import_saved_objects.ts +++ b/src/core/server/saved_objects/import/import_saved_objects.ts @@ -25,6 +25,7 @@ import { SavedObjectsImportOptions, } from './types'; import { validateReferences } from './validate_references'; +import { SavedObject } from '../types'; /** * Import saved objects from given stream. See the {@link SavedObjectsImportOptions | options} for more @@ -67,7 +68,7 @@ export async function importSavedObjectsFromStream({ } // Create objects in bulk - const bulkCreateResult = await savedObjectsClient.bulkCreate(filteredObjects, { + const bulkCreateResult = await savedObjectsClient.bulkCreate(omitVersion(filteredObjects), { overwrite, namespace, }); @@ -82,3 +83,7 @@ export async function importSavedObjectsFromStream({ ...(errorAccumulator.length ? { errors: errorAccumulator } : {}), }; } + +export function omitVersion(objects: SavedObject[]): SavedObject[] { + return objects.map(({ version, ...object }) => object); +} diff --git a/src/core/server/saved_objects/import/resolve_import_errors.ts b/src/core/server/saved_objects/import/resolve_import_errors.ts index a5175aa080598..dce044a31a577 100644 --- a/src/core/server/saved_objects/import/resolve_import_errors.ts +++ b/src/core/server/saved_objects/import/resolve_import_errors.ts @@ -26,6 +26,7 @@ import { SavedObjectsResolveImportErrorsOptions, } from './types'; import { validateReferences } from './validate_references'; +import { omitVersion } from './import_saved_objects'; /** * Resolve and return saved object import errors. @@ -91,7 +92,7 @@ export async function resolveSavedObjectsImportErrors({ // Bulk create in two batches, overwrites and non-overwrites const { objectsToOverwrite, objectsToNotOverwrite } = splitOverwrites(filteredObjects, retries); if (objectsToOverwrite.length) { - const bulkCreateResult = await savedObjectsClient.bulkCreate(objectsToOverwrite, { + const bulkCreateResult = await savedObjectsClient.bulkCreate(omitVersion(objectsToOverwrite), { overwrite: true, namespace, }); @@ -102,9 +103,12 @@ export async function resolveSavedObjectsImportErrors({ successCount += bulkCreateResult.saved_objects.filter((obj) => !obj.error).length; } if (objectsToNotOverwrite.length) { - const bulkCreateResult = await savedObjectsClient.bulkCreate(objectsToNotOverwrite, { - namespace, - }); + const bulkCreateResult = await savedObjectsClient.bulkCreate( + omitVersion(objectsToNotOverwrite), + { + namespace, + } + ); errorAccumulator = [ ...errorAccumulator, ...extractErrors(bulkCreateResult.saved_objects, objectsToNotOverwrite), From a0fc3845e4db856d230dba4276e9dac618dfff87 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Tue, 18 Aug 2020 18:28:02 +0100 Subject: [PATCH 09/10] remove version when loading sample data --- src/plugins/home/server/services/sample_data/routes/install.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/home/server/services/sample_data/routes/install.ts b/src/plugins/home/server/services/sample_data/routes/install.ts index 2d1a53fbb09dc..b94456682afcc 100644 --- a/src/plugins/home/server/services/sample_data/routes/install.ts +++ b/src/plugins/home/server/services/sample_data/routes/install.ts @@ -154,7 +154,7 @@ export function createInstallRoute( let createResults; try { createResults = await context.core.savedObjects.client.bulkCreate( - sampleDataset.savedObjects, + sampleDataset.savedObjects.map(({ version, ...savedObject }) => savedObject), { overwrite: true } ); } catch (err) { From 4297f2a4f5dac590ead08d881881e17f108c8292 Mon Sep 17 00:00:00 2001 From: Gidi Meir Morris Date: Wed, 19 Aug 2020 12:08:45 +0100 Subject: [PATCH 10/10] fixed typo --- src/core/server/saved_objects/service/lib/repository.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index c461fbacc51ca..941c4091a66a7 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -1545,7 +1545,7 @@ describe('SavedObjectsRepository', () => { expect(client.index).toHaveBeenCalled(); }); - it(`should use the ES index with version of ID and version are defined and overwrite=true`, async () => { + it(`should use the ES index with version if ID and version are defined and overwrite=true`, async () => { await createSuccess(type, attributes, { id, overwrite: true, version: mockVersion }); expect(client.index).toHaveBeenCalled();