From a53f0a2124b8119c395385631034585488a9020b Mon Sep 17 00:00:00 2001 From: spalger Date: Fri, 1 Feb 2019 23:56:16 -0800 Subject: [PATCH 01/21] tag discovered uses of version --- .../lib/__tests__/health_check.js | 1 + .../saved_objects/routes/bulk_create.js | 1 + .../saved_objects/routes/bulk_get.test.js | 1 + src/server/saved_objects/routes/update.js | 1 + .../saved_objects/routes/update.test.js | 2 ++ .../saved_objects/serialization/index.ts | 6 ++++ .../serialization/serialization.test.ts | 10 ++++++ .../saved_objects/service/lib/repository.js | 10 ++++++ .../service/lib/repository.test.js | 31 +++++++++++++++++++ .../saved_object/__tests__/saved_object.js | 16 ++++++++-- .../courier/saved_object/saved_object.js | 1 + src/ui/public/doc_table/doc_table.html | 2 ++ .../__tests__/_index_pattern.test.js | 4 +++ .../public/index_patterns/_index_pattern.js | 7 +++++ .../saved_objects/__tests__/saved_object.js | 2 ++ .../__tests__/saved_objects_client.test.js | 3 ++ src/ui/public/saved_objects/saved_object.js | 1 + .../create_or_upgrade_saved_config.js | 3 ++ .../apis/saved_objects/bulk_create.js | 3 ++ .../apis/saved_objects/bulk_get.js | 2 ++ .../apis/saved_objects/create.js | 2 ++ .../apis/saved_objects/find.js | 1 + .../api_integration/apis/saved_objects/get.js | 1 + .../apis/saved_objects/update.js | 1 + .../beats_management/common/domain_types.ts | 2 ++ .../lib/adapters/database/adapter_types.ts | 11 +++++++ .../database/kibana_database_adapter.ts | 1 + .../server/rest_api/beats/enroll.ts | 1 + .../canvas/server/lib/normalize_type.js | 1 + .../infra/server/lib/sources/sources.test.ts | 6 ++++ .../infra/server/lib/sources/sources.ts | 2 ++ .../plugins/infra/server/lib/sources/types.ts | 1 + x-pack/plugins/ml/common/types/jobs.ts | 1 + .../datavisualizer_controller.js | 1 + .../new_job/advanced/new_job_controller.js | 1 + .../server/lib/__tests__/field_format_map.js | 1 + .../__fixtures__/extract_test_file.js | 3 ++ .../__tests__/fixtures/elasticsearch.js | 4 +++ .../server/lib/esqueue/__tests__/worker.js | 11 +++++++ .../reporting/server/lib/esqueue/job.js | 2 ++ .../reporting/server/lib/esqueue/worker.js | 4 +++ .../task_manager/lib/middleware.test.ts | 2 ++ x-pack/plugins/task_manager/task.ts | 1 + .../plugins/task_manager/task_runner.test.ts | 1 + .../plugins/task_manager/task_store.test.ts | 15 +++++++++ x-pack/plugins/task_manager/task_store.ts | 11 +++++++ .../lib/reindexing/reindex_actions.test.ts | 3 ++ .../server/lib/reindexing/reindex_actions.ts | 3 ++ .../api_integration/apis/infra/sources.ts | 6 ++++ .../common/suites/bulk_create.ts | 2 ++ .../common/suites/create.ts | 2 ++ .../common/suites/find.ts | 2 ++ .../common/suites/update.ts | 2 ++ 53 files changed, 213 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js b/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js index 1a334083fb7b5c..73ef4090c0a6e4 100644 --- a/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js +++ b/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js @@ -61,6 +61,7 @@ describe('plugins/elasticsearch', () => { cluster = { callWithInternalUser: sinon.stub() }; cluster.callWithInternalUser.withArgs('index', sinon.match.any).returns(Promise.resolve()); + // TODO-VERSION cluster.callWithInternalUser.withArgs('create', sinon.match.any).returns(Promise.resolve({ _id: '1', _version: 1 })); cluster.callWithInternalUser.withArgs('mget', sinon.match.any).returns(Promise.resolve({ ok: true })); cluster.callWithInternalUser.withArgs('get', sinon.match.any).returns(Promise.resolve({ found: false })); diff --git a/src/server/saved_objects/routes/bulk_create.js b/src/server/saved_objects/routes/bulk_create.js index d2dc14e3f6f7bd..603c9934428c08 100644 --- a/src/server/saved_objects/routes/bulk_create.js +++ b/src/server/saved_objects/routes/bulk_create.js @@ -35,6 +35,7 @@ export const createBulkCreateRoute = prereqs => ({ type: Joi.string().required(), id: Joi.string(), attributes: Joi.object().required(), + // TODO-VERSION version: Joi.number(), migrationVersion: Joi.object().optional(), references: Joi.array().items( diff --git a/src/server/saved_objects/routes/bulk_get.test.js b/src/server/saved_objects/routes/bulk_get.test.js index 62c155a57a165e..76a73dbc50c517 100644 --- a/src/server/saved_objects/routes/bulk_get.test.js +++ b/src/server/saved_objects/routes/bulk_get.test.js @@ -59,6 +59,7 @@ describe('POST /api/saved_objects/_bulk_get', () => { id: 'abc123', type: 'index-pattern', title: 'logstash-*', + // TODO-VERSION version: 2, references: [], }] diff --git a/src/server/saved_objects/routes/update.js b/src/server/saved_objects/routes/update.js index 163fb77d5b62fc..d9197ad6cf4ec7 100644 --- a/src/server/saved_objects/routes/update.js +++ b/src/server/saved_objects/routes/update.js @@ -32,6 +32,7 @@ export const createUpdateRoute = (prereqs) => { }).required(), payload: Joi.object({ attributes: Joi.object().required(), + // TODO-VERSION version: Joi.number().min(1), references: Joi.array().items( Joi.object() diff --git a/src/server/saved_objects/routes/update.test.js b/src/server/saved_objects/routes/update.test.js index 72a540979c2dee..f408d26e0e0720 100644 --- a/src/server/saved_objects/routes/update.test.js +++ b/src/server/saved_objects/routes/update.test.js @@ -67,12 +67,14 @@ describe('PUT /api/saved_objects/{type}/{id?}', () => { it('calls upon savedObjectClient.update', async () => { const attributes = { title: 'Testing' }; + // TODO-VERSION const options = { version: 2, references: [] }; const request = { method: 'PUT', url: '/api/saved_objects/index-pattern/logstash-*', payload: { attributes, + // TODO-VERSION version: options.version } }; diff --git a/src/server/saved_objects/serialization/index.ts b/src/server/saved_objects/serialization/index.ts index 94807ddeb76680..3c8adae6b7f371 100644 --- a/src/server/saved_objects/serialization/index.ts +++ b/src/server/saved_objects/serialization/index.ts @@ -32,6 +32,7 @@ export interface RawDoc { _id: string; _source: any; _type?: string; + // TODO-VERSION _version?: number; } @@ -64,6 +65,7 @@ interface SavedObjectDoc { type: string; namespace?: string; migrationVersion?: MigrationVersion; + // TODO-VERSION version?: number; updated_at?: Date; @@ -116,6 +118,7 @@ export class SavedObjectsSerializer { * * @param {RawDoc} rawDoc - The raw ES document to be converted to saved object format. */ + // TODO-VERSION public rawToSavedObject({ _id, _source, _version }: RawDoc): SanitizedSavedObjectDoc { const { type, namespace } = _source; return { @@ -126,6 +129,7 @@ export class SavedObjectsSerializer { references: _source.references || [], ...(_source.migrationVersion && { migrationVersion: _source.migrationVersion }), ...(_source.updated_at && { updated_at: _source.updated_at }), + // TODO-VERSION ...(_version != null && { version: _version }), }; } @@ -143,6 +147,7 @@ export class SavedObjectsSerializer { attributes, migrationVersion, updated_at, + // TODO-VERSION version, references, } = savedObj; @@ -158,6 +163,7 @@ export class SavedObjectsSerializer { return { _id: this.generateRawId(namespace, type, id), _source: source, + // TODO-VERSION ...(version != null && { _version: version }), }; } diff --git a/src/server/saved_objects/serialization/serialization.test.ts b/src/server/saved_objects/serialization/serialization.test.ts index 2178105fc289e4..5f98d1406c7e4e 100644 --- a/src/server/saved_objects/serialization/serialization.test.ts +++ b/src/server/saved_objects/serialization/serialization.test.ts @@ -86,6 +86,7 @@ describe('saved object conversion', () => { const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); const actual = serializer.rawToSavedObject({ _id: 'hello:world', + // TODO-VERSION _version: 3, _source: { type: 'hello', @@ -103,6 +104,7 @@ describe('saved object conversion', () => { const expected = { id: 'world', type: 'hello', + // TODO-VERSION version: 3, attributes: { a: 'b', @@ -130,10 +132,12 @@ describe('saved object conversion', () => { expect(actual).not.toHaveProperty('version'); }); + // TODO-VERSION test(`if specified it copies _version to version`, () => { const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); const actual = serializer.rawToSavedObject({ _id: 'foo:bar', + // TODO-VERSION _version: 4, _source: { type: 'foo', @@ -222,6 +226,7 @@ describe('saved object conversion', () => { const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); const raw = { _id: 'foo-namespace:foo:bar', + // TODO-VERSION _version: 24, _source: { type: 'foo', @@ -473,17 +478,21 @@ describe('saved object conversion', () => { expect(actual._source).not.toHaveProperty('migrationVersion'); }); + // TODO-VERSION test('it copies the version property to _version', () => { const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); const actual = serializer.savedObjectToRaw({ type: '', attributes: {}, + // TODO-VERSION version: 4, } as any); + // TODO-VERSION expect(actual).toHaveProperty('_version', 4); }); + // TODO-VERSION test(`if unspecified it doesn't add _version property`, () => { const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); const actual = serializer.savedObjectToRaw({ @@ -491,6 +500,7 @@ describe('saved object conversion', () => { attributes: {}, } as any); + // TODO-VERSION expect(actual).not.toHaveProperty('_version'); }); diff --git a/src/server/saved_objects/service/lib/repository.js b/src/server/saved_objects/service/lib/repository.js index e774831afcf492..4b44d247c1f90c 100644 --- a/src/server/saved_objects/service/lib/repository.js +++ b/src/server/saved_objects/service/lib/repository.js @@ -173,6 +173,7 @@ export class SavedObjectsRepository { const { error, _id: responseId, + // TODO-VERSION _version: version, } = Object.values(response)[0]; @@ -188,6 +189,7 @@ export class SavedObjectsRepository { } = rawObjectsToCreate[i]; if (error) { + // TODO-VERSION if (error.type === 'version_conflict_engine_exception') { return { id, @@ -208,6 +210,7 @@ export class SavedObjectsRepository { id, type, updated_at: time, + // TODO-VERSION version, attributes, references, @@ -338,6 +341,7 @@ export class SavedObjectsRepository { ignore: [404], rest_total_hits_as_int: true, body: { + // TODO-VERSION version: true, ...getSearchDsl(this._mappings, this._schema, { search, @@ -423,6 +427,7 @@ export class SavedObjectsRepository { id, type, ...time && { updated_at: time }, + // TODO-VERSION version: doc._version, attributes: doc._source[type], references: doc._source.references || [], @@ -466,6 +471,7 @@ export class SavedObjectsRepository { id, type, ...updatedAt && { updated_at: updatedAt }, + // TODO-VERSION version: response._version, attributes: response._source[type], references: response._source.references || [], @@ -486,6 +492,7 @@ export class SavedObjectsRepository { */ async update(type, id, attributes, options = {}) { const { + // TODO-VERSION version, namespace, references = [], @@ -496,6 +503,7 @@ export class SavedObjectsRepository { id: this._serializer.generateRawId(namespace, type, id), type: this._type, index: this._index, + // TODO-VERSION version, refresh: 'wait_for', ignore: [404], @@ -517,6 +525,7 @@ export class SavedObjectsRepository { id, type, updated_at: time, + // TODO-VERSION version: response._version, references, attributes @@ -593,6 +602,7 @@ export class SavedObjectsRepository { type, updated_at: time, references: response.get._source.references, + // TODO-VERSION version: response._version, attributes: response.get._source[type], }; diff --git a/src/server/saved_objects/service/lib/repository.test.js b/src/server/saved_objects/service/lib/repository.test.js index b0e509e089ee77..c9b9b06ae03f6c 100644 --- a/src/server/saved_objects/service/lib/repository.test.js +++ b/src/server/saved_objects/service/lib/repository.test.js @@ -237,6 +237,7 @@ describe('SavedObjectsRepository', () => { callAdminCluster.callsFake((method, params) => ({ _type: '_doc', _id: params.id, + // TODO-VERSION _version: 2 })); }); @@ -270,6 +271,7 @@ describe('SavedObjectsRepository', () => { type: 'index-pattern', id: 'logstash-*', ...mockTimestampFields, + // TODO-VERSION version: 2, attributes: { title: 'Logstash', @@ -471,6 +473,7 @@ describe('SavedObjectsRepository', () => { create: { error: false, _id: '1', + // TODO-VERSION _version: 1, } }, @@ -478,6 +481,7 @@ describe('SavedObjectsRepository', () => { create: { error: false, _id: '2', + // TODO-VERSION _version: 1, } } @@ -522,6 +526,7 @@ describe('SavedObjectsRepository', () => { { id: 'one', type: 'config', + // TODO-VERSION version: 1, updated_at: mockTimestamp, attributes: { @@ -532,6 +537,7 @@ describe('SavedObjectsRepository', () => { { id: 'two', type: 'index-pattern', + // TODO-VERSION version: 1, updated_at: mockTimestamp, attributes: { @@ -589,6 +595,7 @@ describe('SavedObjectsRepository', () => { create: { _type: '_doc', _id: 'index-pattern:two', + // TODO-VERSION _version: 2 } }] @@ -608,6 +615,7 @@ describe('SavedObjectsRepository', () => { }, { id: 'two', type: 'index-pattern', + // TODO-VERSION version: 2, ...mockTimestampFields, attributes: { title: 'Test Two' }, @@ -624,12 +632,14 @@ describe('SavedObjectsRepository', () => { create: { _type: '_doc', _id: 'config:one', + // TODO-VERSION _version: 2 } }, { create: { _type: '_doc', _id: 'index-pattern:two', + // TODO-VERSION _version: 2 } }] @@ -647,6 +657,7 @@ describe('SavedObjectsRepository', () => { { id: 'one', type: 'config', + // TODO-VERSION version: 2, ...mockTimestampFields, attributes: { title: 'Test One' }, @@ -654,6 +665,7 @@ describe('SavedObjectsRepository', () => { }, { id: 'two', type: 'index-pattern', + // TODO-VERSION version: 2, ...mockTimestampFields, attributes: { title: 'Test Two' }, @@ -952,6 +964,7 @@ describe('SavedObjectsRepository', () => { id: doc._id.replace(/(index-pattern|config|globaltype)\:/, ''), type: doc._source.type, ...mockTimestampFields, + // TODO-VERSION version: doc._version, attributes: doc._source[doc._source.type], references: [], @@ -976,6 +989,7 @@ describe('SavedObjectsRepository', () => { id: doc._id.replace(/(foo-namespace\:)?(index-pattern|config|globaltype)\:/, ''), type: doc._source.type, ...mockTimestampFields, + // TODO-VERSION version: doc._version, attributes: doc._source[doc._source.type], references: [], @@ -1022,6 +1036,7 @@ describe('SavedObjectsRepository', () => { const noNamespaceResult = { _id: 'index-pattern:logstash-*', _type: '_doc', + // TODO-VERSION _version: 2, _source: { type: 'index-pattern', @@ -1035,6 +1050,7 @@ describe('SavedObjectsRepository', () => { const namespacedResult = { _id: 'foo-namespace:index-pattern:logstash-*', _type: '_doc', + // TODO-VERSION _version: 2, _source: { namespace: 'foo-namespace', @@ -1064,6 +1080,7 @@ describe('SavedObjectsRepository', () => { id: 'logstash-*', type: 'index-pattern', updated_at: mockTimestamp, + // TODO-VERSION version: 2, attributes: { title: 'Testing' @@ -1080,6 +1097,7 @@ describe('SavedObjectsRepository', () => { id: 'logstash-*', type: 'index-pattern', updated_at: mockTimestamp, + // TODO-VERSION version: 2, attributes: { title: 'Testing' @@ -1209,6 +1227,7 @@ describe('SavedObjectsRepository', () => { _type: '_doc', _id: 'config:good', found: true, + // TODO-VERSION _version: 2, _source: { ...mockTimestampFields, config: { title: 'Test' } } }, { @@ -1230,6 +1249,7 @@ describe('SavedObjectsRepository', () => { id: 'good', type: 'config', ...mockTimestampFields, + // TODO-VERSION version: 2, attributes: { title: 'Test' }, references: [], @@ -1252,6 +1272,7 @@ describe('SavedObjectsRepository', () => { callAdminCluster.returns(Promise.resolve({ _id: `${type}:${id}`, _type: '_doc', + // TODO-VERSION _version: newVersion, result: 'updated' })); @@ -1280,6 +1301,7 @@ describe('SavedObjectsRepository', () => { id, type, ...mockTimestampFields, + // TODO-VERSION version: newVersion, attributes, references: [{ @@ -1295,11 +1317,13 @@ describe('SavedObjectsRepository', () => { type, id, { title: 'Testing' }, + // TODO-VERSION { version: newVersion - 1 } ); sinon.assert.calledOnce(callAdminCluster); sinon.assert.calledWithExactly(callAdminCluster, sinon.match.string, sinon.match({ + // TODO-VERSION version: newVersion - 1 })); }); @@ -1320,6 +1344,7 @@ describe('SavedObjectsRepository', () => { sinon.assert.calledWithExactly(callAdminCluster, 'update', { type: '_doc', id: 'foo-namespace:index-pattern:logstash-*', + // TODO-VERSION version: undefined, body: { doc: { @@ -1355,6 +1380,7 @@ describe('SavedObjectsRepository', () => { sinon.assert.calledWithExactly(callAdminCluster, 'update', { type: '_doc', id: 'index-pattern:logstash-*', + // TODO-VERSION version: undefined, body: { doc: { @@ -1391,6 +1417,7 @@ describe('SavedObjectsRepository', () => { sinon.assert.calledWithExactly(callAdminCluster, 'update', { type: '_doc', id: 'globaltype:foo', + // TODO-VERSION version: undefined, body: { doc: { @@ -1417,6 +1444,7 @@ describe('SavedObjectsRepository', () => { callAdminCluster.callsFake((method, params) => ({ _type: '_doc', _id: params.id, + // TODO-VERSION _version: 2, _index: '.kibana', get: { @@ -1437,6 +1465,7 @@ describe('SavedObjectsRepository', () => { callAdminCluster.callsFake((method, params) => ({ _type: '_doc', _id: params.id, + // TODO-VERSION _version: 2, _index: '.kibana', get: { @@ -1466,6 +1495,7 @@ describe('SavedObjectsRepository', () => { type: 'config', id: '6.0.0-alpha1', ...mockTimestampFields, + // TODO-VERSION version: 2, attributes: { buildNum: 8468, @@ -1539,6 +1569,7 @@ describe('SavedObjectsRepository', () => { callAdminCluster.callsFake((method, params) => ({ _type: '_doc', _id: params.id, + // TODO-VERSION _version: 2, _index: '.kibana', get: { diff --git a/src/ui/public/courier/saved_object/__tests__/saved_object.js b/src/ui/public/courier/saved_object/__tests__/saved_object.js index 9c0d092557b76a..f61300bebf8e84 100644 --- a/src/ui/public/courier/saved_object/__tests__/saved_object.js +++ b/src/ui/public/courier/saved_object/__tests__/saved_object.js @@ -42,12 +42,14 @@ describe('Saved Object', function () { * that can be used to stub es calls. * @param indexPatternId * @param additionalOptions - object that will be assigned to the mocked doc response. + // TODO-VERSION * @returns {{attributes: {}, type: string, id: *, _version: integer}} */ function getMockedDocResponse(indexPatternId, additionalOptions = {}) { return { type: 'dashboard', id: indexPatternId, + // TODO-VERSION _version: 2, attributes: {}, ...additionalOptions @@ -242,7 +244,12 @@ describe('Saved Object', function () { return createInitializedSavedObject({ type: 'dashboard' }).then(savedObject => { const mockDocResponse = getMockedDocResponse('myId'); sinon.stub(savedObjectsClientStub, 'create').callsFake(() => { - return BluebirdPromise.resolve({ type: 'dashboard', id: 'myId', _version: 2 }); + return BluebirdPromise.resolve({ + type: 'dashboard', + id: 'myId', + // TODO-VERSION + _version: 2 + }); }); stubESResponse(mockDocResponse); @@ -261,7 +268,10 @@ describe('Saved Object', function () { sinon.stub(savedObjectsClientStub, 'create').callsFake(() => { expect(savedObject.isSaving).to.be(true); return BluebirdPromise.resolve({ - type: 'dashboard', id, version: 2 + type: 'dashboard', + id, + // TODO-VERSION + version: 2 }); }); expect(savedObject.isSaving).to.be(false); @@ -300,6 +310,7 @@ describe('Saved Object', function () { sinon.stub(savedObjectsClientStub, 'create').callsFake(() => { return BluebirdPromise.resolve({ id, + // TODO-VERSION version: 2, type: 'dashboard', }); @@ -544,6 +555,7 @@ describe('Saved Object', function () { attributes: { title: 'testIndexPattern' }, + // TODO-VERSION _version: 2 }); diff --git a/src/ui/public/courier/saved_object/saved_object.js b/src/ui/public/courier/saved_object/saved_object.js index c3cf9be9491bbe..8222b63d37f593 100644 --- a/src/ui/public/courier/saved_object/saved_object.js +++ b/src/ui/public/courier/saved_object/saved_object.js @@ -226,6 +226,7 @@ export function SavedObjectProvider(Promise, Private, Notifier, confirmModalProm _type: resp.type, _source: _.cloneDeep(resp.attributes), references: resp.references, + // TODO-VERSION found: resp._version ? true : false }; }) diff --git a/src/ui/public/doc_table/doc_table.html b/src/ui/public/doc_table/doc_table.html index c035a36dfe907c..e05ceafe9ce5a9 100644 --- a/src/ui/public/doc_table/doc_table.html +++ b/src/ui/public/doc_table/doc_table.html @@ -37,6 +37,7 @@ on-remove-column="onRemoveColumn" > + + ({ jest.mock('../../saved_objects', () => { const object = { + // TODO-VERSION _version: 1, _id: 'foo', attributes: { @@ -96,7 +97,9 @@ jest.mock('../../saved_objects', () => { return { SavedObjectsClientProvider: { get: async () => object, + // TODO-VERSION update: async (type, id, body, { version }) => { + // TODO-VERSION if (object._version !== version) { throw { res: { @@ -109,6 +112,7 @@ jest.mock('../../saved_objects', () => { return { id: object._id, + // TODO-VERSION _version: ++object._version, }; } diff --git a/src/ui/public/index_patterns/_index_pattern.js b/src/ui/public/index_patterns/_index_pattern.js index 434c5a96f584f7..bfe36161a8b4b6 100644 --- a/src/ui/public/index_patterns/_index_pattern.js +++ b/src/ui/public/index_patterns/_index_pattern.js @@ -179,6 +179,7 @@ export function IndexPatternProvider(Private, config, Promise, confirmModalPromi return id; } + // TODO-VERSION function setVersion(indexPattern, version) { indexPattern.version = version; return version; @@ -246,12 +247,14 @@ export function IndexPatternProvider(Private, config, Promise, confirmModalPromi .then(resp => { // temporary compatability for savedObjectsClient + // TODO-VERSION setVersion(this, resp._version); return { _id: resp.id, _type: resp.type, _source: _.cloneDeep(resp.attributes), + // TODO-VERSION found: resp._version ? true : false }; }) @@ -465,9 +468,12 @@ export function IndexPatternProvider(Private, config, Promise, confirmModalPromi const body = this.prepBody(); // What keys changed since they last pulled the index pattern const originalChangedKeys = Object.keys(body).filter(key => body[key] !== this.originalBody[key]); + // TODO-VERSION return savedObjectsClient.update(type, this.id, body, { version: this.version }) + // TODO-VERSION .then(({ id, _version }) => { setId(this, id); + // TODO-VERSION setVersion(this, _version); }) .catch(err => { @@ -510,6 +516,7 @@ export function IndexPatternProvider(Private, config, Promise, confirmModalPromi this[key] = samePattern[key]; }); + // TODO-VERSION setVersion(this, samePattern.version); // Clear cache diff --git a/src/ui/public/saved_objects/__tests__/saved_object.js b/src/ui/public/saved_objects/__tests__/saved_object.js index 8b2dd84d184f3a..6ad5f102a3f489 100644 --- a/src/ui/public/saved_objects/__tests__/saved_object.js +++ b/src/ui/public/saved_objects/__tests__/saved_object.js @@ -46,8 +46,10 @@ describe('SavedObject', () => { const version = 2; const client = sinon.stub(); + // TODO-VERSION const savedObject = new SavedObject(client, { version }); + // TODO-VERSION expect(savedObject._version).to.be(version); }); }); diff --git a/src/ui/public/saved_objects/__tests__/saved_objects_client.test.js b/src/ui/public/saved_objects/__tests__/saved_objects_client.test.js index 4a8de1d12b5e95..fa39e694b5a6a3 100644 --- a/src/ui/public/saved_objects/__tests__/saved_objects_client.test.js +++ b/src/ui/public/saved_objects/__tests__/saved_objects_client.test.js @@ -29,6 +29,7 @@ describe('SavedObjectsClient', () => { id: 'AVwSwFxtcMV38qjDZoQg', type: 'config', attributes: { title: 'Example title' }, + // TODO-VERSION version: 2 }; @@ -228,7 +229,9 @@ describe('SavedObjectsClient', () => { test('makes HTTP call', () => { const attributes = { foo: 'Foo', bar: 'Bar' }; + // TODO-VERSION const body = { attributes, version: 2 }; + // TODO-VERSION const options = { version: 2 }; savedObjectsClient.update('index-pattern', 'logstash-*', attributes, options); diff --git a/src/ui/public/saved_objects/saved_object.js b/src/ui/public/saved_objects/saved_object.js index ed3bbfe9b0fb1a..07bb8906a35da6 100644 --- a/src/ui/public/saved_objects/saved_object.js +++ b/src/ui/public/saved_objects/saved_object.js @@ -26,6 +26,7 @@ export class SavedObject { this.type = type; this.attributes = attributes || {}; this.references = references || []; + // TODO-VERSION this._version = version; this.migrationVersion = migrationVersion; if (error) { diff --git a/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js b/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js index 9c36233d0d1f9f..bd67cb3e84f88f 100644 --- a/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js +++ b/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js @@ -41,6 +41,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function () { create: sinon.stub().callsFake(async (type, attributes, options = {}) => ({ type, id: options.id, + // TODO-VERSION version: 1, })) }; @@ -48,6 +49,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function () { async function run(options = {}) { const resp = await createOrUpgradeSavedConfig({ savedObjectsClient, + // TODO-VERSION version, buildNum, logWithMetadata, @@ -55,6 +57,7 @@ describe('uiSettings/createOrUpgradeSavedConfig', function () { }); sinon.assert.calledOnce(getUpgradeableConfig); + // TODO-VERSION sinon.assert.alwaysCalledWith(getUpgradeableConfig, { savedObjectsClient, version }); return resp; diff --git a/test/api_integration/apis/saved_objects/bulk_create.js b/test/api_integration/apis/saved_objects/bulk_create.js index 074af9f775dde0..7f29e01f9129c4 100644 --- a/test/api_integration/apis/saved_objects/bulk_create.js +++ b/test/api_integration/apis/saved_objects/bulk_create.js @@ -66,6 +66,7 @@ export default function ({ getService }) { type: 'dashboard', id: 'a01b2f57-fcfd-4864-b735-09e28f0d815e', updated_at: resp.body.saved_objects[1].updated_at, + // TODO-VERSION version: 1, attributes: { title: 'A great new dashboard' @@ -99,6 +100,7 @@ export default function ({ getService }) { type: 'visualization', id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', updated_at: resp.body.saved_objects[0].updated_at, + // TODO-VERSION version: 1, attributes: { title: 'An existing visualization' @@ -109,6 +111,7 @@ export default function ({ getService }) { type: 'dashboard', id: 'a01b2f57-fcfd-4864-b735-09e28f0d815e', updated_at: resp.body.saved_objects[1].updated_at, + // TODO-VERSION version: 1, attributes: { title: 'A great new dashboard' diff --git a/test/api_integration/apis/saved_objects/bulk_get.js b/test/api_integration/apis/saved_objects/bulk_get.js index da208a5cbe70ad..d02dd602654f27 100644 --- a/test/api_integration/apis/saved_objects/bulk_get.js +++ b/test/api_integration/apis/saved_objects/bulk_get.js @@ -59,6 +59,7 @@ export default function ({ getService }) { }, type: 'visualization', updated_at: '2017-09-21T18:51:23.794Z', + // TODO-VERSION version: resp.body.saved_objects[0].version, attributes: { title: 'Count of requests', @@ -90,6 +91,7 @@ export default function ({ getService }) { id: '7.0.0-alpha1', type: 'config', updated_at: '2017-09-21T18:49:16.302Z', + // TODO-VERSION version: resp.body.saved_objects[2].version, attributes: { buildNum: 8467, diff --git a/test/api_integration/apis/saved_objects/create.js b/test/api_integration/apis/saved_objects/create.js index a4e66318fb01ee..60a457438c458c 100644 --- a/test/api_integration/apis/saved_objects/create.js +++ b/test/api_integration/apis/saved_objects/create.js @@ -51,6 +51,7 @@ export default function ({ getService }) { visualization: '7.0.0' }, updated_at: resp.body.updated_at, + // TODO-VERSION version: 1, attributes: { title: 'My favorite vis' @@ -96,6 +97,7 @@ export default function ({ getService }) { visualization: '7.0.0' }, updated_at: resp.body.updated_at, + // TODO-VERSION version: 1, attributes: { title: 'My favorite vis' diff --git a/test/api_integration/apis/saved_objects/find.js b/test/api_integration/apis/saved_objects/find.js index 515f4501517bcc..a9ffb5cc060f28 100644 --- a/test/api_integration/apis/saved_objects/find.js +++ b/test/api_integration/apis/saved_objects/find.js @@ -42,6 +42,7 @@ export default function ({ getService }) { { type: 'visualization', id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', + // TODO-VERSION version: 1, attributes: { 'title': 'Count of requests' diff --git a/test/api_integration/apis/saved_objects/get.js b/test/api_integration/apis/saved_objects/get.js index 0734918f5f3e4a..4c2ab262fdc7f0 100644 --- a/test/api_integration/apis/saved_objects/get.js +++ b/test/api_integration/apis/saved_objects/get.js @@ -41,6 +41,7 @@ export default function ({ getService }) { }, type: 'visualization', updated_at: '2017-09-21T18:51:23.794Z', + // TODO-VERSION version: resp.body.version, migrationVersion: { visualization: '7.0.0', diff --git a/test/api_integration/apis/saved_objects/update.js b/test/api_integration/apis/saved_objects/update.js index a00ab69783cb07..604fa38177450c 100644 --- a/test/api_integration/apis/saved_objects/update.js +++ b/test/api_integration/apis/saved_objects/update.js @@ -48,6 +48,7 @@ export default function ({ getService }) { id: resp.body.id, type: 'visualization', updated_at: resp.body.updated_at, + // TODO-VERSION version: 2, attributes: { title: 'My second favorite vis' diff --git a/x-pack/plugins/beats_management/common/domain_types.ts b/x-pack/plugins/beats_management/common/domain_types.ts index 858e25ff5f562f..4d74d1a5976968 100644 --- a/x-pack/plugins/beats_management/common/domain_types.ts +++ b/x-pack/plugins/beats_management/common/domain_types.ts @@ -45,6 +45,7 @@ export interface CMBeat { access_token: string; verified_on?: string; type: string; + // TODO-VERSION version?: string; host_ip: string; host_name: string; @@ -62,6 +63,7 @@ export interface CMBeat { export interface ConfigBlockSchema { id: string; name: string; + // TODO-VERSION version: number; allowOtherConfigs?: boolean; configs: BeatConfigSchema[]; diff --git a/x-pack/plugins/beats_management/server/lib/adapters/database/adapter_types.ts b/x-pack/plugins/beats_management/server/lib/adapters/database/adapter_types.ts index ea86dc79bd6d08..40642fb56359f1 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/database/adapter_types.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/database/adapter_types.ts @@ -100,6 +100,7 @@ export interface DatabaseSearchResponse { _id: string; _score: number; _source: T; + // TODO-VERSION _version?: number; _explanation?: DatabaseExplanation; fields?: any; @@ -128,6 +129,7 @@ export interface DatabaseGetDocumentResponse { _index: string; _type: string; _id: string; + // TODO-VERSION _version: number; found: boolean; _source: Source; @@ -182,6 +184,7 @@ export interface DatabaseDeleteDocumentParams extends DatabaseGenericParams { refresh?: DatabaseRefresh; routing?: string; timeout?: string; + // TODO-VERSION version?: number; versionType?: DatabaseVersionType; index: string; @@ -194,6 +197,7 @@ export interface DatabaseIndexDocumentResponse { _index: string; _type: string; _id: string; + // TODO-VERSION _version: number; result: string; } @@ -203,6 +207,7 @@ export interface DatabaseUpdateDocumentResponse { _index: string; _type: string; _id: string; + // TODO-VERSION _version: number; result: string; } @@ -212,6 +217,7 @@ export interface DatabaseDeleteDocumentResponse { _index: string; _type: string; _id: string; + // TODO-VERSION _version: number; result: string; } @@ -225,6 +231,7 @@ export interface DatabaseIndexDocumentParams extends DatabaseGenericParams { timeout?: string; timestamp?: Date | number; ttl?: string; + // TODO-VERSION version?: number; versionType?: DatabaseVersionType; pipeline?: string; @@ -246,6 +253,7 @@ export interface DatabaseCreateDocumentParams extends DatabaseGenericParams { timeout?: string; timestamp?: Date | number; ttl?: string; + // TODO-VERSION version?: number; versionType?: DatabaseVersionType; pipeline?: string; @@ -265,6 +273,7 @@ export interface DatabaseDeleteDocumentParams extends DatabaseGenericParams { refresh?: DatabaseRefresh; routing?: string; timeout?: string; + // TODO-VERSION version?: number; versionType?: DatabaseVersionType; index: string; @@ -282,6 +291,7 @@ export interface DatabaseGetParams extends DatabaseGenericParams { _source?: DatabaseNameList; _sourceExclude?: DatabaseNameList; _source_includes?: DatabaseNameList; + // TODO-VERSION version?: number; versionType?: DatabaseVersionType; id: string; @@ -310,6 +320,7 @@ export interface DatabaseDeleteDocumentResponse { _index: string; _type: string; _id: string; + // TODO-VERSION _version: number; result: string; } diff --git a/x-pack/plugins/beats_management/server/lib/adapters/database/kibana_database_adapter.ts b/x-pack/plugins/beats_management/server/lib/adapters/database/kibana_database_adapter.ts index f097994509ee4d..2aab29417559c0 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/database/kibana_database_adapter.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/database/kibana_database_adapter.ts @@ -131,6 +131,7 @@ export class KibanaDatabaseAdapter implements DatabaseAdapter { _id: string; _score: number; _source: Source; + // TODO-VERSION _version?: number; fields?: any; highlight?: any; diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts b/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts index 9f3feb4651bd29..7b1691200d89c2 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts @@ -27,6 +27,7 @@ export const createBeatEnrollmentRoute = (libs: CMServerLibs) => ({ host_name: Joi.string().required(), name: Joi.string().required(), type: Joi.string().required(), + // TODO-VERSION version: Joi.string().required(), }).required(), }, diff --git a/x-pack/plugins/canvas/server/lib/normalize_type.js b/x-pack/plugins/canvas/server/lib/normalize_type.js index b1dd880334308a..83f71272507dea 100644 --- a/x-pack/plugins/canvas/server/lib/normalize_type.js +++ b/x-pack/plugins/canvas/server/lib/normalize_type.js @@ -17,6 +17,7 @@ export function normalizeType(type) { 'short', 'byte', 'token_count', + // TODO-VERSION '_version', ], date: ['date', 'datetime'], diff --git a/x-pack/plugins/infra/server/lib/sources/sources.test.ts b/x-pack/plugins/infra/server/lib/sources/sources.test.ts index b26f37eeefadc3..df0a2324289bc5 100644 --- a/x-pack/plugins/infra/server/lib/sources/sources.test.ts +++ b/x-pack/plugins/infra/server/lib/sources/sources.test.ts @@ -14,6 +14,7 @@ describe('the InfraSources lib', () => { configuration: createMockStaticConfiguration({}), savedObjects: createMockSavedObjectsService({ id: 'TEST_ID', + // TODO-VERSION version: 1, updated_at: '2000-01-01T00:00:00.000Z', attributes: { @@ -34,6 +35,7 @@ describe('the InfraSources lib', () => { expect(await sourcesLib.getSourceConfiguration(request, 'TEST_ID')).toMatchObject({ id: 'TEST_ID', + // TODO-VERSION version: 1, updatedAt: 946684800000, configuration: { @@ -66,6 +68,7 @@ describe('the InfraSources lib', () => { }), savedObjects: createMockSavedObjectsService({ id: 'TEST_ID', + // TODO-VERSION version: 1, updated_at: '2000-01-01T00:00:00.000Z', attributes: { @@ -80,6 +83,7 @@ describe('the InfraSources lib', () => { expect(await sourcesLib.getSourceConfiguration(request, 'TEST_ID')).toMatchObject({ id: 'TEST_ID', + // TODO-VERSION version: 1, updatedAt: 946684800000, configuration: { @@ -101,6 +105,7 @@ describe('the InfraSources lib', () => { configuration: createMockStaticConfiguration({}), savedObjects: createMockSavedObjectsService({ id: 'TEST_ID', + // TODO-VERSION version: 1, updated_at: '2000-01-01T00:00:00.000Z', attributes: {}, @@ -111,6 +116,7 @@ describe('the InfraSources lib', () => { expect(await sourcesLib.getSourceConfiguration(request, 'TEST_ID')).toMatchObject({ id: 'TEST_ID', + // TODO-VERSION version: 1, updatedAt: 946684800000, configuration: { diff --git a/x-pack/plugins/infra/server/lib/sources/sources.ts b/x-pack/plugins/infra/server/lib/sources/sources.ts index d4b42a29847a59..8957e83c5a0357 100644 --- a/x-pack/plugins/infra/server/lib/sources/sources.ts +++ b/x-pack/plugins/infra/server/lib/sources/sources.ts @@ -44,6 +44,7 @@ export class InfraSources { this.libs.savedObjects.SavedObjectsClient.errors.isNotFoundError(err) ? Promise.resolve({ id: sourceId, + // TODO-VERSION version: undefined, updatedAt: undefined, configuration: staticDefaultSourceConfiguration, @@ -112,6 +113,7 @@ export class InfraSources { ) { const staticDefaultSourceConfiguration = await this.getStaticDefaultSourceConfiguration(); + // TODO-VERSION const { configuration, version } = await this.getSourceConfiguration(request, sourceId); const updatedConfigurationAttributes = updaters.reduce( diff --git a/x-pack/plugins/infra/server/lib/sources/types.ts b/x-pack/plugins/infra/server/lib/sources/types.ts index 3b1d3e4e49edbc..17db11b6b2b591 100644 --- a/x-pack/plugins/infra/server/lib/sources/types.ts +++ b/x-pack/plugins/infra/server/lib/sources/types.ts @@ -51,6 +51,7 @@ export const InfraSavedSourceConfigurationRuntimeType = runtimeTypes.intersectio attributes: PartialInfraSourceConfigurationRuntimeType, }), runtimeTypes.partial({ + // TODO-VERSION version: runtimeTypes.number, updated_at: TimestampFromString, }), diff --git a/x-pack/plugins/ml/common/types/jobs.ts b/x-pack/plugins/ml/common/types/jobs.ts index 5484a288308212..dfbffb7fb88069 100644 --- a/x-pack/plugins/ml/common/types/jobs.ts +++ b/x-pack/plugins/ml/common/types/jobs.ts @@ -29,6 +29,7 @@ export interface MlJob { finished_time: number; job_id: string; job_type: string; + // TODO-VERSION job_version: string; model_plot_config: object; model_size_stats: object; diff --git a/x-pack/plugins/ml/public/datavisualizer/datavisualizer_controller.js b/x-pack/plugins/ml/public/datavisualizer/datavisualizer_controller.js index 8403d6bf47b04a..b7ebc4b5f6a043 100644 --- a/x-pack/plugins/ml/public/datavisualizer/datavisualizer_controller.js +++ b/x-pack/plugins/ml/public/datavisualizer/datavisualizer_controller.js @@ -72,6 +72,7 @@ module // List of system fields we don't want to display. // TODO - are we happy to ignore these fields? + // TODO-VERSION const OMIT_FIELDS = ['_source', '_type', '_index', '_id', '_version', '_score']; $scope.metricCards = []; diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js index 5dea21cf7af866..83839046d9ae80 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js @@ -106,6 +106,7 @@ module.controller('MlNewJob', '_source', '_type', '_uid', + // TODO-VERSION '_version', '_feature', '_ignored', diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js index 4e545fb4c1a3aa..48af5f6856e723 100644 --- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js +++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js @@ -17,6 +17,7 @@ describe('field format map', function () { const indexPatternSavedObject = { id: 'logstash-*', type: 'index-pattern', + // TODO-VERSION version: 4, attributes: { title: 'logstash-*', diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js index 33a83f01f53ea7..a3c24b83263513 100644 --- a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js +++ b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js @@ -3,6 +3,7 @@ export const search = { _index: '.kibana', _type: 'search', _id: 'mock-search', + // TODO-VERSION _version: 1, found: true, _source: { @@ -30,6 +31,7 @@ export const visualization = { _index: '.kibana', _type: 'visualization', _id: 'mock-visualization', + // TODO-VERSION _version: 1, found: true, _source: { @@ -53,6 +55,7 @@ export const dashboard = { _index: '.kibana', _type: 'dashboard', _id: 'mock-dashboard', + // TODO-VERSION _version: 1, found: true, _source: { diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/fixtures/elasticsearch.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/fixtures/elasticsearch.js index 4e64f426e90444..a6345e30d6a8c6 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/fixtures/elasticsearch.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/fixtures/elasticsearch.js @@ -18,6 +18,7 @@ ClientMock.prototype.index = function (params = {}) { _index: params.index || 'index', _type: params.type || constants.DEFAULT_SETTING_DOCTYPE, _id: params.id || uniqueId('testDoc'), + // TODO-VERSION _version: 1, _shards: { total: shardCount, successful: shardCount, failed: 0 }, created: true @@ -53,6 +54,7 @@ ClientMock.prototype.get = function (params = {}, source = {}) { _index: params.index || 'index', _type: params.type || constants.DEFAULT_SETTING_DOCTYPE, _id: params.id || 'AVRPRLnlp7Ur1SZXfT-T', + // TODO-VERSION _version: params.version || 1, found: true, _source: _source @@ -65,6 +67,7 @@ ClientMock.prototype.search = function (params = {}, count = 5, source = {}) { _index: params.index || 'index', _type: params.type || constants.DEFAULT_SETTING_DOCTYPE, _id: uniqueId('documentId'), + // TODO-VERSION _version: random(1, 5), _score: null, _source: { @@ -96,6 +99,7 @@ ClientMock.prototype.update = function (params = {}) { _index: params.index || 'index', _type: params.type || constants.DEFAULT_SETTING_DOCTYPE, _id: params.id || uniqueId('testDoc'), + // TODO-VERSION _version: params.version + 1 || 2, _shards: { total: shardCount, successful: shardCount, failed: 0 }, created: true diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js index 15fa81954d7ddf..2aac19b40a0852 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js @@ -336,8 +336,10 @@ describe('Worker class', function () { searchStub = sinon.stub(mockQueue.client, 'search').callsFake(() => Promise.resolve({ hits: { hits: [] } })); }); + // TODO-VERSION it('should query with version', function () { const params = getSearchParams(); + // TODO-VERSION expect(params).to.have.property('version', true); }); @@ -432,6 +434,7 @@ describe('Worker class', function () { index: 'myIndex', type: 'test', id: 12345, + // TODO-VERSION version: 3 }; return mockQueue.client.get(params) @@ -446,12 +449,14 @@ describe('Worker class', function () { clock.restore(); }); + // TODO-VERSION it('should use version on update', function () { worker._claimJob(job); const query = updateSpy.firstCall.args[0]; expect(query).to.have.property('index', job._index); expect(query).to.have.property('type', job._type); expect(query).to.have.property('id', job._id); + // TODO-VERSION expect(query).to.have.property('version', job._version); }); @@ -500,6 +505,7 @@ describe('Worker class', function () { expect(msg).to.equal(false); }); + // TODO-VERSION it('should reject the promise on version errors', function () { mockQueue.client.update.restore(); sinon.stub(mockQueue.client, 'update').returns(Promise.reject({ statusCode: 409 })); @@ -524,6 +530,7 @@ describe('Worker class', function () { _index: 'myIndex', _type: 'test', _id: 12345, + // TODO-VERSION _version: 3, found: true, _source: { @@ -608,12 +615,14 @@ describe('Worker class', function () { clock.restore(); }); + // TODO-VERSION it('should use version on update', function () { worker._failJob(job); const query = updateSpy.firstCall.args[0]; expect(query).to.have.property('index', job._index); expect(query).to.have.property('type', job._type); expect(query).to.have.property('id', job._id); + // TODO-VERSION expect(query).to.have.property('version', job._version); }); @@ -631,6 +640,7 @@ describe('Worker class', function () { expect(doc.output).to.have.property('content', msg); }); + // TODO-VERSION it('should return true on version mismatch errors', function () { mockQueue.client.update.restore(); sinon.stub(mockQueue.client, 'update').returns(Promise.reject({ statusCode: 409 })); @@ -735,6 +745,7 @@ describe('Worker class', function () { expect(query).to.have.property('index', job._index); expect(query).to.have.property('type', job._type); expect(query).to.have.property('id', job._id); + // TODO-VERSION expect(query).to.have.property('version', job._version); expect(query.body.doc).to.have.property('output'); expect(query.body.doc.output).to.have.property('content_type', false); diff --git a/x-pack/plugins/reporting/server/lib/esqueue/job.js b/x-pack/plugins/reporting/server/lib/esqueue/job.js index cf8eeacfbe92ed..ca83d6ec4990ac 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/job.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/job.js @@ -82,6 +82,7 @@ export class Job extends events.EventEmitter { id: doc._id, type: doc._type, index: doc._index, + // TODO-VERSION version: doc._version, }; this.debug(`Job created in index ${this.index}`); @@ -118,6 +119,7 @@ export class Job extends events.EventEmitter { index: doc._index, id: doc._id, type: doc._type, + // TODO-VERSION version: doc._version, }); }); diff --git a/x-pack/plugins/reporting/server/lib/esqueue/worker.js b/x-pack/plugins/reporting/server/lib/esqueue/worker.js index c5fa020fb76c60..6187a4005408ff 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/worker.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/worker.js @@ -130,6 +130,7 @@ export class Worker extends events.EventEmitter { index: job._index, type: job._type, id: job._id, + // TODO-VERSION version: job._version, body: { doc } }) @@ -167,6 +168,7 @@ export class Worker extends events.EventEmitter { index: job._index, type: job._type, id: job._id, + // TODO-VERSION version: job._version, body: { doc } }) @@ -244,6 +246,7 @@ export class Worker extends events.EventEmitter { index: job._index, type: job._type, id: job._id, + // TODO-VERSION version: job._version, body: { doc } }) @@ -385,6 +388,7 @@ export class Worker extends events.EventEmitter { return this.client.search({ index: `${this.queue.index}-*`, type: this.doctype, + // TODO-VERSION version: true, body: query }) diff --git a/x-pack/plugins/task_manager/lib/middleware.test.ts b/x-pack/plugins/task_manager/lib/middleware.test.ts index c249f86d159219..5822f9ecdef425 100644 --- a/x-pack/plugins/task_manager/lib/middleware.test.ts +++ b/x-pack/plugins/task_manager/lib/middleware.test.ts @@ -20,6 +20,7 @@ const getMockTaskInstance = () => ({ const getMockConcreteTaskInstance = () => { const concrete: { id: string; + // TODO-VERSION version: number; attempts: number; status: TaskStatus; @@ -29,6 +30,7 @@ const getMockConcreteTaskInstance = () => { params: any; } = { id: 'hy8o99o83', + // TODO-VERSION version: 1, attempts: 0, status: 'idle', diff --git a/x-pack/plugins/task_manager/task.ts b/x-pack/plugins/task_manager/task.ts index 71f61ea0576b8e..de154761ea6f10 100644 --- a/x-pack/plugins/task_manager/task.ts +++ b/x-pack/plugins/task_manager/task.ts @@ -208,6 +208,7 @@ export interface ConcreteTaskInstance extends TaskInstance { /** * The version of the Elaticsearch document. */ + // TODO-VERSION version: number; /** diff --git a/x-pack/plugins/task_manager/task_runner.test.ts b/x-pack/plugins/task_manager/task_runner.test.ts index a3866c65f9d19e..4a465c703bdb62 100644 --- a/x-pack/plugins/task_manager/task_runner.test.ts +++ b/x-pack/plugins/task_manager/task_runner.test.ts @@ -230,6 +230,7 @@ describe('TaskManagerRunner', () => { { id: 'foo', taskType: 'bar', + // TODO-VERSION version: 32, runAt: new Date(), attempts: 0, diff --git a/x-pack/plugins/task_manager/task_store.test.ts b/x-pack/plugins/task_manager/task_store.test.ts index c69ab4e20e016f..1708191ce4aaf5 100644 --- a/x-pack/plugins/task_manager/task_store.test.ts +++ b/x-pack/plugins/task_manager/task_store.test.ts @@ -42,6 +42,7 @@ describe('TaskStore', () => { const callCluster = sinon.spy(() => Promise.resolve({ _id: 'testid', + // TODO-VERSION _version: 3344, }) ); @@ -89,6 +90,7 @@ describe('TaskStore', () => { expect(result).toMatchObject({ ...task, + // TODO-VERSION version: 3344, id: 'testid', }); @@ -255,6 +257,7 @@ describe('TaskStore', () => { status: 'idle', taskType: 'foo', user: 'jimbo', + // TODO-VERSION version: undefined, }, { @@ -268,6 +271,7 @@ describe('TaskStore', () => { status: 'running', taskType: 'bar', user: 'dabo', + // TODO-VERSION version: undefined, }, ], @@ -345,6 +349,7 @@ describe('TaskStore', () => { }, size: 10, sort: { 'task.runAt': { order: 'asc' } }, + // TODO-VERSION version: true, }, index, @@ -405,6 +410,7 @@ describe('TaskStore', () => { status: 'idle', taskType: 'foo', user: 'jimbo', + // TODO-VERSION version: undefined, }, { @@ -418,6 +424,7 @@ describe('TaskStore', () => { status: 'running', taskType: 'bar', user: 'dabo', + // TODO-VERSION version: undefined, }, ]); @@ -425,6 +432,7 @@ describe('TaskStore', () => { }); describe('update', () => { + // TODO-VERSION test('refreshes the index, handles versioning', async () => { const runAt = new Date(); const task = { @@ -433,11 +441,13 @@ describe('TaskStore', () => { params: { hello: 'world' }, state: { foo: 'bar' }, taskType: 'report', + // TODO-VERSION version: 2, attempts: 3, status: 'idle' as TaskStatus, }; + // TODO-VERSION const callCluster = sinon.spy(async () => ({ _version: task.version + 1 })); const store = new TaskStore({ callCluster, @@ -454,11 +464,13 @@ describe('TaskStore', () => { expect(callCluster.args[0][1]).toMatchObject({ id: task.id, index: 'tasky', + // TODO-VERSION version: 2, refresh: true, body: { doc: { task: { + // TODO-VERSION ...['id', 'version'].reduce((acc, prop) => _.omit(acc, prop), task), params: JSON.stringify(task.params), state: JSON.stringify(task.state), @@ -467,6 +479,7 @@ describe('TaskStore', () => { }, }); + // TODO-VERSION expect(result).toEqual({ ...task, version: 3 }); }); }); @@ -478,6 +491,7 @@ describe('TaskStore', () => { Promise.resolve({ _index: 'myindex', _id: id, + // TODO-VERSION _version: 32, result: 'deleted', }) @@ -496,6 +510,7 @@ describe('TaskStore', () => { expect(result).toEqual({ id, index: 'myindex', + // TODO-VERSION version: 32, result: 'deleted', }); diff --git a/x-pack/plugins/task_manager/task_store.ts b/x-pack/plugins/task_manager/task_store.ts index 4cc14610f4d316..be77749c44653c 100644 --- a/x-pack/plugins/task_manager/task_store.ts +++ b/x-pack/plugins/task_manager/task_store.ts @@ -33,6 +33,7 @@ export interface FetchResult { export interface RemoveResult { index: string; id: string; + // TODO-VERSION version: string; result: string; } @@ -41,6 +42,7 @@ export interface RemoveResult { export interface RawTaskDoc { _id: string; _index: string; + // TODO-VERSION _version: number; _source: { type: string; @@ -179,6 +181,7 @@ export class TaskStore { return { ...taskInstance, id: result._id, + // TODO-VERSION version: result._version, attempts: 0, status: task.status, @@ -225,6 +228,7 @@ export class TaskStore { }, size: 10, sort: { 'task.runAt': { order: 'asc' } }, + // TODO-VERSION version: true, }); @@ -241,12 +245,14 @@ export class TaskStore { public async update(doc: ConcreteTaskInstance): Promise { const rawDoc = taskDocToRaw(doc, this.index); + // TODO-VERSION const { _version } = await this.callCluster('update', { body: { doc: rawDoc._source, }, id: doc.id, index: this.index, + // TODO-VERSION version: doc.version, // The refresh is important so that if we immediately look for work, // we don't pick up this task. @@ -255,6 +261,7 @@ export class TaskStore { return { ...doc, + // TODO-VERSION version: _version, }; } @@ -277,6 +284,7 @@ export class TaskStore { return { index: result._index, id: result._id, + // TODO-VERSION version: result._version, result: result.result, }; @@ -333,6 +341,7 @@ function rawSource(doc: TaskInstance) { }; delete (source as any).id; + // TODO-VERSION delete (source as any).version; delete (source as any).type; @@ -350,6 +359,7 @@ function taskDocToRaw(doc: ConcreteTaskInstance, index: string): RawTaskDoc { _id: doc.id, _index: index, _source: { type, task }, + // TODO-VERSION _version: doc.version, }; } @@ -358,6 +368,7 @@ function rawToTaskDoc(doc: RawTaskDoc): ConcreteTaskInstance { return { ...doc._source.task, id: doc._id, + // TODO-VERSION version: doc._version, params: parseJSONField(doc._source.task.params, 'params', doc), state: parseJSONField(doc._source.task.state, 'state', doc), diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts index d766dcc3385743..e4d8a6bebeb1ca 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts @@ -91,6 +91,7 @@ describe('ReindexActions', () => { type: REINDEX_OP_TYPE, id: '9', attributes: { indexName: 'hi', locked: moment().format() }, + // TODO-VERSION version: 1, } as ReindexSavedObject, { newIndexName: 'test' } @@ -101,6 +102,7 @@ describe('ReindexActions', () => { expect(args[1]).toEqual('9'); expect(args[2].indexName).toEqual('hi'); expect(args[2].newIndexName).toEqual('test'); + // TODO-VERSION expect(args[3]).toEqual({ version: 1 }); }); @@ -111,6 +113,7 @@ describe('ReindexActions', () => { type: REINDEX_OP_TYPE, id: '10', attributes: { indexName: 'hi', locked: null }, + // TODO-VERSION version: 1, } as ReindexSavedObject, { newIndexName: 'test' } diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts index 30fe268c639535..fde9e98d3ae644 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts @@ -158,6 +158,7 @@ export const reindexActionsFactory = ( REINDEX_OP_TYPE, reindexOp.id, { ...reindexOp.attributes, locked: moment().format() }, + // TODO-VERSION { version: reindexOp.version } ); }; @@ -167,6 +168,7 @@ export const reindexActionsFactory = ( REINDEX_OP_TYPE, reindexOp.id, { ...reindexOp.attributes, locked: null }, + // TODO-VERSION { version: reindexOp.version } ); }; @@ -198,6 +200,7 @@ export const reindexActionsFactory = ( const newAttrs = { ...reindexOp.attributes, locked: moment().format(), ...attrs }; return client.update(REINDEX_OP_TYPE, reindexOp.id, newAttrs, { + // TODO-VERSION version: reindexOp.version, }); }, diff --git a/x-pack/test/api_integration/apis/infra/sources.ts b/x-pack/test/api_integration/apis/infra/sources.ts index 3a63f5769009e5..646d8c318b528c 100644 --- a/x-pack/test/api_integration/apis/infra/sources.ts +++ b/x-pack/test/api_integration/apis/infra/sources.ts @@ -69,6 +69,7 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); + // TODO-VERSION const { version, updatedAt, configuration, status } = response.data && response.data.createSource.source; @@ -98,6 +99,7 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); + // TODO-VERSION const { version, updatedAt, configuration, status } = response.data && response.data.createSource.source; @@ -160,6 +162,7 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); + // TODO-VERSION const { version } = creationResponse.data && creationResponse.data.createSource.source; expect(version).to.be.greaterThan(0); @@ -189,6 +192,7 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); + // TODO-VERSION const { version: initialVersion, updatedAt: createdAt } = creationResponse.data && creationResponse.data.createSource.source; @@ -258,6 +262,7 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); + // TODO-VERSION const { version: initialVersion, updatedAt: createdAt } = creationResponse.data && creationResponse.data.createSource.source; @@ -300,6 +305,7 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); + // TODO-VERSION const { version: initialVersion, updatedAt: createdAt } = creationResponse.data && creationResponse.data.createSource.source; diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts index 6dcaae760a58d3..71cd954bbaf5b2 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts @@ -84,6 +84,7 @@ export function bulkCreateTestSuiteFactory(es: any, esArchiver: any, supertest: type: 'dashboard', id: `${getIdPrefix(spaceId)}a01b2f57-fcfd-4864-b735-09e28f0d815e`, updated_at: resp.body.saved_objects[1].updated_at, + // TODO-VERSION version: 1, attributes: { title: 'A great new dashboard', @@ -94,6 +95,7 @@ export function bulkCreateTestSuiteFactory(es: any, esArchiver: any, supertest: type: 'globaltype', id: `05976c65-1145-4858-bbf0-d225cc78a06e`, updated_at: resp.body.saved_objects[2].updated_at, + // TODO-VERSION version: 1, attributes: { name: 'A new globaltype object', diff --git a/x-pack/test/saved_object_api_integration/common/suites/create.ts b/x-pack/test/saved_object_api_integration/common/suites/create.ts index 19bb2b232c94ed..6a928d2e7db192 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/create.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/create.ts @@ -63,6 +63,7 @@ export function createTestSuiteFactory(es: any, esArchiver: any, supertest: Supe }, type: spaceAwareType, updated_at: resp.body.updated_at, + // TODO-VERSION version: 1, attributes: { title: 'My favorite vis', @@ -104,6 +105,7 @@ export function createTestSuiteFactory(es: any, esArchiver: any, supertest: Supe id: resp.body.id, type: notSpaceAwareType, updated_at: resp.body.updated_at, + // TODO-VERSION version: 1, attributes: { name: `Can't be contained to a space`, diff --git a/x-pack/test/saved_object_api_integration/common/suites/find.ts b/x-pack/test/saved_object_api_integration/common/suites/find.ts index db135a40ca9bf3..bae298bcc7f643 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/find.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/find.ts @@ -63,6 +63,7 @@ export function findTestSuiteFactory(esArchiver: any, supertest: SuperTest) { type: 'globaltype', id: `8121a00-8efd-21e7-1cb3-34ab966434445`, + // TODO-VERSION version: 1, attributes: { name: 'My favorite global object', @@ -96,6 +97,7 @@ export function findTestSuiteFactory(esArchiver: any, supertest: SuperTest) { type: 'visualization', id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, + // TODO-VERSION version: 1, attributes: { title: 'Count of requests', diff --git a/x-pack/test/saved_object_api_integration/common/suites/update.ts b/x-pack/test/saved_object_api_integration/common/suites/update.ts index 5d496ba58bbba4..d67142c2de38d7 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/update.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/update.ts @@ -74,6 +74,7 @@ export function updateTestSuiteFactory(esArchiver: any, supertest: SuperTest Date: Sat, 2 Feb 2019 00:19:22 -0800 Subject: [PATCH 02/21] discovery round two --- src/server/saved_objects/routes/update.js | 2 ++ src/server/saved_objects/service/lib/repository.js | 7 +++++++ src/server/saved_objects/service/lib/repository.test.js | 3 +++ src/server/saved_objects/service/saved_objects_client.js | 6 ++++++ .../index_patterns/__tests__/_index_pattern.test.js | 3 +++ src/ui/public/saved_objects/saved_object.js | 1 + src/ui/public/saved_objects/saved_objects_client.js | 8 ++++++++ x-pack/plugins/infra/server/lib/sources/sources.ts | 2 ++ x-pack/plugins/reporting/server/lib/esqueue/worker.js | 1 + .../saved_objects_client/spaces_saved_objects_client.ts | 6 ++++++ x-pack/test/api_integration/apis/infra/sources.ts | 5 +++++ .../common/suites/bulk_get.ts | 3 +++ .../saved_object_api_integration/common/suites/get.ts | 2 ++ 13 files changed, 49 insertions(+) diff --git a/src/server/saved_objects/routes/update.js b/src/server/saved_objects/routes/update.js index d9197ad6cf4ec7..c23219bb3c3d51 100644 --- a/src/server/saved_objects/routes/update.js +++ b/src/server/saved_objects/routes/update.js @@ -47,7 +47,9 @@ export const createUpdateRoute = (prereqs) => { handler(request) { const { savedObjectsClient } = request.pre; const { type, id } = request.params; + // TODO-VERSION const { attributes, version, references } = request.payload; + // TODO-VERSION const options = { version, references }; return savedObjectsClient.update(type, id, attributes, options); diff --git a/src/server/saved_objects/service/lib/repository.js b/src/server/saved_objects/service/lib/repository.js index 4b44d247c1f90c..5719ef20955f3e 100644 --- a/src/server/saved_objects/service/lib/repository.js +++ b/src/server/saved_objects/service/lib/repository.js @@ -73,6 +73,7 @@ export class SavedObjectsRepository { * @property {object} [options.migrationVersion=undefined] * @property {string} [options.namespace] * @property {array} [options.references] - [{ name, type, id }] + * // TODO-VERSION * @returns {promise} - { id, type, version, attributes } */ async create(type, attributes = {}, options = {}) { @@ -129,6 +130,7 @@ export class SavedObjectsRepository { * @param {object} [options={}] * @property {boolean} [options.overwrite=false] - overwrites existing documents * @property {string} [options.namespace] + * // TODO-VERSION * @returns {promise} - {saved_objects: [[{ id, type, version, references, attributes, error: { message } }]} */ async bulkCreate(objects, options = {}) { @@ -262,6 +264,7 @@ export class SavedObjectsRepository { * Deletes all objects from the provided namespace. * * @param {string} namespace + * // TODO-VERSION * @returns {promise} - { took, timed_out, total, deleted, batches, version_conflicts, noops, retries, failures } */ async deleteByNamespace(namespace) { @@ -304,6 +307,7 @@ export class SavedObjectsRepository { * @property {Array} [options.fields] * @property {string} [options.namespace] * @property {object} [options.hasReference] - { type, id } + * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes }], total, per_page, page } */ async find(options = {}) { @@ -383,6 +387,7 @@ export class SavedObjectsRepository { * @param {array} objects - an array ids, or an array of objects containing id and optionally type * @param {object} [options={}] * @property {string} [options.namespace] + * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes }] } * @example * @@ -444,6 +449,7 @@ export class SavedObjectsRepository { * @param {string} id * @param {object} [options={}] * @property {string} [options.namespace] + * // TODO-VERSION * @returns {promise} - { id, type, version, attributes } */ async get(type, id, options = {}) { @@ -485,6 +491,7 @@ export class SavedObjectsRepository { * @param {string} type * @param {string} id * @param {object} [options={}] + * // TODO-VERSION * @property {integer} options.version - ensures version matches that of persisted object * @property {string} [options.namespace] * @property {array} [options.references] - [{ name, type, id }] diff --git a/src/server/saved_objects/service/lib/repository.test.js b/src/server/saved_objects/service/lib/repository.test.js index c9b9b06ae03f6c..7552f7a855901f 100644 --- a/src/server/saved_objects/service/lib/repository.test.js +++ b/src/server/saved_objects/service/lib/repository.test.js @@ -168,6 +168,7 @@ describe('SavedObjectsRepository', () => { total: 23, deleted: 23, batches: 1, + // TODO-VERSION version_conflicts: 0, noops: 0, retries: { bulk: 0, search: 0 }, @@ -1288,6 +1289,7 @@ describe('SavedObjectsRepository', () => { sinon.assert.calledOnce(migrator.awaitMigration); }); + // TODO-VERSION it('returns current ES document version', async () => { const response = await savedObjectsRepository.update('index-pattern', 'logstash-*', attributes, { namespace: 'foo-namespace', @@ -1312,6 +1314,7 @@ describe('SavedObjectsRepository', () => { }); }); + // TODO-VERSION it('accepts version', async () => { await savedObjectsRepository.update( type, diff --git a/src/server/saved_objects/service/saved_objects_client.js b/src/server/saved_objects/service/saved_objects_client.js index a18881ad09d41a..b05c13ce67397e 100644 --- a/src/server/saved_objects/service/saved_objects_client.js +++ b/src/server/saved_objects/service/saved_objects_client.js @@ -103,6 +103,7 @@ export class SavedObjectsClient { * @property {string} [options.id] - force id on creation, not recommended * @property {boolean} [options.overwrite=false] * @property {string} [options.namespace] + * // TODO-VERSION * @returns {promise} - { id, type, version, attributes } */ async create(type, attributes = {}, options = {}) { @@ -116,6 +117,7 @@ export class SavedObjectsClient { * @param {object} [options={}] * @property {boolean} [options.overwrite=false] - overwrites existing documents * @property {string} [options.namespace] + * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes, error: { message } }]} */ async bulkCreate(objects, options = {}) { @@ -149,6 +151,7 @@ export class SavedObjectsClient { * @property {Array} [options.fields] * @property {string} [options.namespace] * @property {object} [options.hasReference] - { type, id } + * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes }], total, per_page, page } */ async find(options = {}) { @@ -161,6 +164,7 @@ export class SavedObjectsClient { * @param {array} objects - an array ids, or an array of objects containing id and optionally type * @param {object} [options={}] * @property {string} [options.namespace] + * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes }] } * @example * @@ -180,6 +184,7 @@ export class SavedObjectsClient { * @param {string} id * @param {object} [options={}] * @property {string} [options.namespace] + * // TODO-VERSION * @returns {promise} - { id, type, version, attributes } */ async get(type, id, options = {}) { @@ -192,6 +197,7 @@ export class SavedObjectsClient { * @param {string} type * @param {string} id * @param {object} [options={}] + * // TODO-VERSION * @property {integer} options.version - ensures version matches that of persisted object * @property {string} [options.namespace] * @returns {promise} diff --git a/src/ui/public/index_patterns/__tests__/_index_pattern.test.js b/src/ui/public/index_patterns/__tests__/_index_pattern.test.js index ec5eba06e983d4..26db4895871815 100644 --- a/src/ui/public/index_patterns/__tests__/_index_pattern.test.js +++ b/src/ui/public/index_patterns/__tests__/_index_pattern.test.js @@ -134,6 +134,7 @@ const kbnUrl = { const i18n = arg => arg; describe('IndexPattern', () => { + // TODO-VERSION it('should handle version conflicts', async () => { const IndexPattern = IndexPatternProvider(Private, config, Promise, confirmModalPromise, kbnUrl, i18n); // eslint-disable-line new-cap @@ -141,12 +142,14 @@ describe('IndexPattern', () => { const pattern = new IndexPattern('foo'); await pattern.init(); + // TODO-VERSION expect(pattern.version).toBe(2); // Create the same one - we're going to handle concurrency const samePattern = new IndexPattern('foo'); await samePattern.init(); + // TODO-VERSION expect(samePattern.version).toBe(3); // This will conflict because samePattern did a save (from refreshFields) diff --git a/src/ui/public/saved_objects/saved_object.js b/src/ui/public/saved_objects/saved_object.js index 07bb8906a35da6..931bddb4cdcefe 100644 --- a/src/ui/public/saved_objects/saved_object.js +++ b/src/ui/public/saved_objects/saved_object.js @@ -20,6 +20,7 @@ import _ from 'lodash'; export class SavedObject { + // TODO-VERSION constructor(client, { id, type, version, attributes, error, migrationVersion, references } = {}) { this._client = client; this.id = id; diff --git a/src/ui/public/saved_objects/saved_objects_client.js b/src/ui/public/saved_objects/saved_objects_client.js index 0ee4c2ff47ad32..a7af6da0c193e0 100644 --- a/src/ui/public/saved_objects/saved_objects_client.js +++ b/src/ui/public/saved_objects/saved_objects_client.js @@ -52,6 +52,7 @@ export class SavedObjectsClient { * @property {boolean} [options.overwrite=false] * @property {object} [options.migrationVersion] * @property {array} [options.references] [{ name, type, id }] + * // TODO-VERSION * @returns {promise} - SavedObject({ id, type, version, attributes }) */ create = (type, attributes = {}, options = {}) => { @@ -89,6 +90,7 @@ export class SavedObjectsClient { * @param {array} objects - [{ type, id, attributes, references, migrationVersion }] * @param {object} [options={}] * @property {boolean} [options.overwrite=false] + * // TODO-VERSION * @returns {promise} - { savedObjects: [{ id, type, version, attributes, error: { message } }]} */ bulkCreate = (objects = [], options = {}) => { @@ -129,6 +131,7 @@ export class SavedObjectsClient { * @property {integer} [options.perPage=20] * @property {array} options.fields * @property {object} [options.hasReference] - { type, id } + * // TODO-VERSION * @returns {promise} - { savedObjects: [ SavedObject({ id, type, version, attributes }) ]} */ find = (options = {}) => { @@ -146,6 +149,7 @@ export class SavedObjectsClient { * * @param {string} type * @param {string} id + * // TODO-VERSION * @returns {promise} - SavedObject({ id, type, version, attributes }) */ get = (type, id) => { @@ -163,6 +167,7 @@ export class SavedObjectsClient { * Returns an array of objects by id * * @param {array} objects - an array ids, or an array of objects containing id and optionally type + * // TODO-VERSION * @returns {promise} - { savedObjects: [ SavedObject({ id, type, version, attributes }) ] } * @example * @@ -188,11 +193,13 @@ export class SavedObjectsClient { * @param {string} id * @param {object} attributes * @param {object} options + * // TODO-VERSION * @prop {integer} options.version - ensures version matches that of persisted object * @prop {object} options.migrationVersion - The optional migrationVersion of this document * @prop {array} option.references - the references of the saved object * @returns {promise} */ + // TODO-VERSION update(type, id, attributes, { version, migrationVersion, references } = {}) { if (!type || !id || !attributes) { return Promise.reject(new Error('requires type, id and attributes')); @@ -203,6 +210,7 @@ export class SavedObjectsClient { attributes, migrationVersion, references, + // TODO-VERSION version }; diff --git a/x-pack/plugins/infra/server/lib/sources/sources.ts b/x-pack/plugins/infra/server/lib/sources/sources.ts index 8957e83c5a0357..124df11c9e10b6 100644 --- a/x-pack/plugins/infra/server/lib/sources/sources.ts +++ b/x-pack/plugins/infra/server/lib/sources/sources.ts @@ -129,6 +129,7 @@ export class InfraSources { sourceId, { ...updatedConfigurationAttributes }, { + // TODO-VERSION version, } ) @@ -204,6 +205,7 @@ const convertSavedObjectToSavedSourceConfiguration = (savedObject: unknown) => InfraSavedSourceConfigurationRuntimeType.decode(savedObject) .map(savedSourceConfiguration => ({ id: savedSourceConfiguration.id, + // TODO-VERSION version: savedSourceConfiguration.version, updatedAt: savedSourceConfiguration.updated_at, configuration: savedSourceConfiguration.attributes, diff --git a/x-pack/plugins/reporting/server/lib/esqueue/worker.js b/x-pack/plugins/reporting/server/lib/esqueue/worker.js index 6187a4005408ff..2500d6b5c5d760 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/worker.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/worker.js @@ -328,6 +328,7 @@ export class Worker extends events.EventEmitter { return claimResult; }) .catch((err) => { + // TODO-VERSION if (err.statusCode === 409) { this.warn(`_claimPendingJobs encountered a version conflict on updating pending job ${job._id}`, err); return; // continue reducing and looking for a different job to claim diff --git a/x-pack/plugins/spaces/server/lib/saved_objects_client/spaces_saved_objects_client.ts b/x-pack/plugins/spaces/server/lib/saved_objects_client/spaces_saved_objects_client.ts index 9a3203305b59d2..142c80b2d5be1f 100644 --- a/x-pack/plugins/spaces/server/lib/saved_objects_client/spaces_saved_objects_client.ts +++ b/x-pack/plugins/spaces/server/lib/saved_objects_client/spaces_saved_objects_client.ts @@ -82,6 +82,7 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient { * @property {string} [options.id] - force id on creation, not recommended * @property {boolean} [options.overwrite=false] * @property {string} [options.namespace] + * // TODO-VERSION * @returns {promise} - { id, type, version, attributes } */ public async create( @@ -105,6 +106,7 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient { * @param {object} [options={}] * @property {boolean} [options.overwrite=false] - overwrites existing documents * @property {string} [options.namespace] + * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes, error: { message } }]} */ public async bulkCreate(objects: BulkCreateObject[], options: BaseOptions = {}) { @@ -150,6 +152,7 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient { * @property {Array} [options.fields] * @property {string} [options.namespace] * @property {object} [options.hasReference] - { type, id } + * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes }], total, per_page, page } */ public async find(options: FindOptions = {}) { @@ -174,6 +177,7 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient { * @param {array} objects - an array ids, or an array of objects containing id and optionally type * @param {object} [options={}] * @property {string} [options.namespace] + * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes }] } * @example * @@ -199,6 +203,7 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient { * @param {string} id * @param {object} [options={}] * @property {string} [options.namespace] + * // TODO-VERSION * @returns {promise} - { id, type, version, attributes } */ public async get(type: string, id: string, options: BaseOptions = {}) { @@ -217,6 +222,7 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient { * @param {string} type * @param {string} id * @param {object} [options={}] + * // TODO-VERSION * @property {integer} options.version - ensures version matches that of persisted object * @property {string} [options.namespace] * @returns {promise} diff --git a/x-pack/test/api_integration/apis/infra/sources.ts b/x-pack/test/api_integration/apis/infra/sources.ts index 646d8c318b528c..06c081188e3813 100644 --- a/x-pack/test/api_integration/apis/infra/sources.ts +++ b/x-pack/test/api_integration/apis/infra/sources.ts @@ -233,6 +233,7 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); + // TODO-VERSION const { version, updatedAt, configuration, status } = updateResponse.data && updateResponse.data.updateSource.source; @@ -283,6 +284,7 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); + // TODO-VERSION const { version, updatedAt, configuration, status } = updateResponse.data && updateResponse.data.updateSource.source; @@ -326,6 +328,7 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); + // TODO-VERSION const { version, updatedAt, configuration } = updateResponse.data && updateResponse.data.updateSource.source; @@ -349,6 +352,7 @@ const createSourceMutation = gql` createSource(id: $sourceId, source: $source) { source { id + // TODO-VERSION version updatedAt configuration { @@ -386,6 +390,7 @@ const updateSourceMutation = gql` updateSource(id: $sourceId, changes: $changes) { source { id + // TODO-VERSION version updatedAt configuration { diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts index e82ea7b856a8c4..248cf25d5eed57 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_get.ts @@ -65,6 +65,7 @@ export function bulkGetTestSuiteFactory(esArchiver: any, supertest: SuperTest) id: `${notSpaceAwareId}`, type: 'globaltype', updated_at: '2017-09-21T18:59:16.270Z', + // TODO-VERSION version: resp.body.version, attributes: { name: 'My favorite global object', @@ -99,6 +100,7 @@ export function getTestSuiteFactory(esArchiver: any, supertest: SuperTest) visualization: '7.0.0', }, updated_at: '2017-09-21T18:51:23.794Z', + // TODO-VERSION version: resp.body.version, attributes: { title: 'Count of requests', From 24cbf26637bfaf95dc1c90f5e29bbc4a354c7d5d Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 02:12:44 -0800 Subject: [PATCH 03/21] [savedObjects] version = _seq_no + _primary_term --- .../saved_objects/routes/bulk_create.js | 3 +- .../saved_objects/routes/bulk_get.test.js | 3 +- src/server/saved_objects/routes/update.js | 5 +- .../saved_objects/routes/update.test.js | 4 +- .../saved_objects/serialization/index.ts | 25 ++-- .../serialization/serialization.test.ts | 77 ++++++++---- .../saved_objects/service/lib/errors.d.ts | 3 + .../saved_objects/service/lib/errors.js | 9 ++ .../saved_objects/service/lib/repository.js | 38 ++---- .../service/lib/repository.test.js | 115 ++++++++---------- .../saved_objects/service/lib/version.ts | 90 ++++++++++++++ .../service/saved_objects_client.js | 6 - .../saved_objects/__tests__/saved_object.js | 3 - .../__tests__/saved_objects_client.test.js | 9 +- src/ui/public/saved_objects/saved_object.js | 2 - .../saved_objects/saved_objects_client.js | 8 -- 16 files changed, 238 insertions(+), 162 deletions(-) create mode 100644 src/server/saved_objects/service/lib/version.ts diff --git a/src/server/saved_objects/routes/bulk_create.js b/src/server/saved_objects/routes/bulk_create.js index 603c9934428c08..e5b21f6e8e17eb 100644 --- a/src/server/saved_objects/routes/bulk_create.js +++ b/src/server/saved_objects/routes/bulk_create.js @@ -35,8 +35,7 @@ export const createBulkCreateRoute = prereqs => ({ type: Joi.string().required(), id: Joi.string(), attributes: Joi.object().required(), - // TODO-VERSION - version: Joi.number(), + version: Joi.string(), migrationVersion: Joi.object().optional(), references: Joi.array().items( Joi.object() diff --git a/src/server/saved_objects/routes/bulk_get.test.js b/src/server/saved_objects/routes/bulk_get.test.js index 76a73dbc50c517..6a8dd2bdcb75a9 100644 --- a/src/server/saved_objects/routes/bulk_get.test.js +++ b/src/server/saved_objects/routes/bulk_get.test.js @@ -59,8 +59,7 @@ describe('POST /api/saved_objects/_bulk_get', () => { id: 'abc123', type: 'index-pattern', title: 'logstash-*', - // TODO-VERSION - version: 2, + version: 'foo', references: [], }] }; diff --git a/src/server/saved_objects/routes/update.js b/src/server/saved_objects/routes/update.js index c23219bb3c3d51..4f5aed4eecb315 100644 --- a/src/server/saved_objects/routes/update.js +++ b/src/server/saved_objects/routes/update.js @@ -32,8 +32,7 @@ export const createUpdateRoute = (prereqs) => { }).required(), payload: Joi.object({ attributes: Joi.object().required(), - // TODO-VERSION - version: Joi.number().min(1), + version: Joi.string(), references: Joi.array().items( Joi.object() .keys({ @@ -47,9 +46,7 @@ export const createUpdateRoute = (prereqs) => { handler(request) { const { savedObjectsClient } = request.pre; const { type, id } = request.params; - // TODO-VERSION const { attributes, version, references } = request.payload; - // TODO-VERSION const options = { version, references }; return savedObjectsClient.update(type, id, attributes, options); diff --git a/src/server/saved_objects/routes/update.test.js b/src/server/saved_objects/routes/update.test.js index f408d26e0e0720..fc76815c95c081 100644 --- a/src/server/saved_objects/routes/update.test.js +++ b/src/server/saved_objects/routes/update.test.js @@ -67,14 +67,12 @@ describe('PUT /api/saved_objects/{type}/{id?}', () => { it('calls upon savedObjectClient.update', async () => { const attributes = { title: 'Testing' }; - // TODO-VERSION - const options = { version: 2, references: [] }; + const options = { version: 'foo', references: [] }; const request = { method: 'PUT', url: '/api/saved_objects/index-pattern/logstash-*', payload: { attributes, - // TODO-VERSION version: options.version } }; diff --git a/src/server/saved_objects/serialization/index.ts b/src/server/saved_objects/serialization/index.ts index 3c8adae6b7f371..74bfe9443bd5ee 100644 --- a/src/server/saved_objects/serialization/index.ts +++ b/src/server/saved_objects/serialization/index.ts @@ -24,6 +24,7 @@ import uuid from 'uuid'; import { SavedObjectsSchema } from '../schema'; +import { decodeVersion, encodeVersion } from '../service/lib/version'; /** * A raw document as represented directly in the saved object index. @@ -32,8 +33,8 @@ export interface RawDoc { _id: string; _source: any; _type?: string; - // TODO-VERSION - _version?: number; + _seq_no?: number; + _primary_term?: number; } /** @@ -65,8 +66,7 @@ interface SavedObjectDoc { type: string; namespace?: string; migrationVersion?: MigrationVersion; - // TODO-VERSION - version?: number; + version?: string; updated_at?: Date; [rootProp: string]: any; @@ -118,9 +118,15 @@ export class SavedObjectsSerializer { * * @param {RawDoc} rawDoc - The raw ES document to be converted to saved object format. */ - // TODO-VERSION - public rawToSavedObject({ _id, _source, _version }: RawDoc): SanitizedSavedObjectDoc { + public rawToSavedObject(doc: RawDoc): SanitizedSavedObjectDoc { + const { _id, _source, _seq_no, _primary_term } = doc; const { type, namespace } = _source; + + const version = + _seq_no != null || _primary_term != null + ? encodeVersion(_seq_no!, _primary_term!) + : undefined; + return { type, id: this.trimIdPrefix(namespace, type, _id), @@ -129,8 +135,7 @@ export class SavedObjectsSerializer { references: _source.references || [], ...(_source.migrationVersion && { migrationVersion: _source.migrationVersion }), ...(_source.updated_at && { updated_at: _source.updated_at }), - // TODO-VERSION - ...(_version != null && { version: _version }), + ...(version && { version }), }; } @@ -147,7 +152,6 @@ export class SavedObjectsSerializer { attributes, migrationVersion, updated_at, - // TODO-VERSION version, references, } = savedObj; @@ -163,8 +167,7 @@ export class SavedObjectsSerializer { return { _id: this.generateRawId(namespace, type, id), _source: source, - // TODO-VERSION - ...(version != null && { _version: version }), + ...(version != null && decodeVersion(version)), }; } diff --git a/src/server/saved_objects/serialization/serialization.test.ts b/src/server/saved_objects/serialization/serialization.test.ts index 5f98d1406c7e4e..ce2090e88d11fc 100644 --- a/src/server/saved_objects/serialization/serialization.test.ts +++ b/src/server/saved_objects/serialization/serialization.test.ts @@ -20,6 +20,7 @@ import _ from 'lodash'; import { SavedObjectsSerializer } from '.'; import { SavedObjectsSchema } from '../schema'; +import { encodeVersion } from '../service/lib/version'; describe('saved object conversion', () => { describe('#rawToSavedObject', () => { @@ -86,8 +87,8 @@ describe('saved object conversion', () => { const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); const actual = serializer.rawToSavedObject({ _id: 'hello:world', - // TODO-VERSION - _version: 3, + _seq_no: 3, + _primary_term: 1, _source: { type: 'hello', hello: { @@ -104,8 +105,7 @@ describe('saved object conversion', () => { const expected = { id: 'world', type: 'hello', - // TODO-VERSION - version: 3, + version: encodeVersion(3, 1), attributes: { a: 'b', c: 'd', @@ -132,19 +132,46 @@ describe('saved object conversion', () => { expect(actual).not.toHaveProperty('version'); }); - // TODO-VERSION - test(`if specified it copies _version to version`, () => { + test(`if specified it encodes _seq_no and _primary_term to version`, () => { const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); const actual = serializer.rawToSavedObject({ _id: 'foo:bar', - // TODO-VERSION - _version: 4, + _seq_no: 4, + _primary_term: 1, _source: { type: 'foo', hello: {}, }, }); - expect(actual).toHaveProperty('version', 4); + expect(actual).toHaveProperty('version', encodeVersion(4, 1)); + }); + + test(`if only _seq_no is specified it throws`, () => { + const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); + expect(() => + serializer.rawToSavedObject({ + _id: 'foo:bar', + _seq_no: 4, + _source: { + type: 'foo', + hello: {}, + }, + }) + ).toThrowErrorMatchingInlineSnapshot(`"_primary_term from elasticsearch must be an integer"`); + }); + + test(`if only _primary_term is throws`, () => { + const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); + expect(() => + serializer.rawToSavedObject({ + _id: 'foo:bar', + _primary_term: 1, + _source: { + type: 'foo', + hello: {}, + }, + }) + ).toThrowErrorMatchingInlineSnapshot(`"_seq_no from elasticsearch must be an integer"`); }); test('if specified it copies the _source.updated_at property to updated_at', () => { @@ -226,8 +253,8 @@ describe('saved object conversion', () => { const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); const raw = { _id: 'foo-namespace:foo:bar', - // TODO-VERSION - _version: 24, + _primary_term: 24, + _seq_no: 42, _source: { type: 'foo', foo: { @@ -478,30 +505,38 @@ describe('saved object conversion', () => { expect(actual._source).not.toHaveProperty('migrationVersion'); }); - // TODO-VERSION - test('it copies the version property to _version', () => { + test('it decodes the version property to _seq_no and _primary_term', () => { const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); const actual = serializer.savedObjectToRaw({ type: '', attributes: {}, - // TODO-VERSION - version: 4, + version: encodeVersion(1, 2), } as any); - // TODO-VERSION - expect(actual).toHaveProperty('_version', 4); + expect(actual).toHaveProperty('_seq_no', 1); + expect(actual).toHaveProperty('_primary_term', 2); }); - // TODO-VERSION - test(`if unspecified it doesn't add _version property`, () => { + test(`if unspecified it doesn't add _seq_no or _primary_term properties`, () => { const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); const actual = serializer.savedObjectToRaw({ type: '', attributes: {}, } as any); - // TODO-VERSION - expect(actual).not.toHaveProperty('_version'); + expect(actual).not.toHaveProperty('_seq_no'); + expect(actual).not.toHaveProperty('_primary_term'); + }); + + test(`if version invalid it throws`, () => { + const serializer = new SavedObjectsSerializer(new SavedObjectsSchema()); + expect(() => + serializer.savedObjectToRaw({ + type: '', + attributes: {}, + version: 'foo', + } as any) + ).toThrowErrorMatchingInlineSnapshot(`"Invalid version [foo]"`); }); test('it copies attributes to _source[type]', () => { diff --git a/src/server/saved_objects/service/lib/errors.d.ts b/src/server/saved_objects/service/lib/errors.d.ts index 5cc16993de9b84..cfeed417b98da7 100644 --- a/src/server/saved_objects/service/lib/errors.d.ts +++ b/src/server/saved_objects/service/lib/errors.d.ts @@ -25,3 +25,6 @@ export function isNotFoundError(maybeError: any): boolean; export function isConflictError(maybeError: any): boolean; export function isEsUnavailableError(maybeError: any): boolean; export function isEsAutoCreateIndexError(maybeError: any): boolean; + +export function createInvalidVersionError(version: any): Error; +export function isInvalidVersionError(maybeError: Error): boolean; diff --git a/src/server/saved_objects/service/lib/errors.js b/src/server/saved_objects/service/lib/errors.js index d0a4d6ecec796d..d54a812d9b3140 100644 --- a/src/server/saved_objects/service/lib/errors.js +++ b/src/server/saved_objects/service/lib/errors.js @@ -50,6 +50,15 @@ export function isBadRequestError(error) { return error && error[code] === CODE_BAD_REQUEST; } +// 400 - invalid version +const CODE_INVALID_VERSION = 'SavedObjectsClient/invalidVersion'; +export function createInvalidVersionError(versionInput) { + return decorate(Boom.badRequest(`Invalid version [${versionInput}]`), CODE_INVALID_VERSION, 400); +} +export function isInvalidVersionError(error) { + return error && error[code] === CODE_INVALID_VERSION; +} + // 401 - Not Authorized const CODE_NOT_AUTHORIZED = 'SavedObjectsClient/notAuthorized'; diff --git a/src/server/saved_objects/service/lib/repository.js b/src/server/saved_objects/service/lib/repository.js index 5719ef20955f3e..70723ba36a52bd 100644 --- a/src/server/saved_objects/service/lib/repository.js +++ b/src/server/saved_objects/service/lib/repository.js @@ -23,6 +23,7 @@ import { getSearchDsl } from './search_dsl'; import { includedFields } from './included_fields'; import { decorateEsError } from './decorate_es_error'; import * as errors from './errors'; +import { decodeRequestVersion, encodeVersion, encodeHitVersion } from './version'; // BEWARE: The SavedObjectClient depends on the implementation details of the SavedObjectsRepository // so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient. @@ -73,7 +74,6 @@ export class SavedObjectsRepository { * @property {object} [options.migrationVersion=undefined] * @property {string} [options.namespace] * @property {array} [options.references] - [{ name, type, id }] - * // TODO-VERSION * @returns {promise} - { id, type, version, attributes } */ async create(type, attributes = {}, options = {}) { @@ -130,7 +130,6 @@ export class SavedObjectsRepository { * @param {object} [options={}] * @property {boolean} [options.overwrite=false] - overwrites existing documents * @property {string} [options.namespace] - * // TODO-VERSION * @returns {promise} - {saved_objects: [[{ id, type, version, references, attributes, error: { message } }]} */ async bulkCreate(objects, options = {}) { @@ -175,8 +174,8 @@ export class SavedObjectsRepository { const { error, _id: responseId, - // TODO-VERSION - _version: version, + _seq_no: seqNo, + _primary_term: primaryTerm, } = Object.values(response)[0]; const { @@ -191,7 +190,6 @@ export class SavedObjectsRepository { } = rawObjectsToCreate[i]; if (error) { - // TODO-VERSION if (error.type === 'version_conflict_engine_exception') { return { id, @@ -212,8 +210,7 @@ export class SavedObjectsRepository { id, type, updated_at: time, - // TODO-VERSION - version, + version: encodeVersion(seqNo, primaryTerm), attributes, references, }; @@ -264,11 +261,9 @@ export class SavedObjectsRepository { * Deletes all objects from the provided namespace. * * @param {string} namespace - * // TODO-VERSION * @returns {promise} - { took, timed_out, total, deleted, batches, version_conflicts, noops, retries, failures } */ async deleteByNamespace(namespace) { - if (!namespace || typeof namespace !== 'string') { throw new TypeError(`namespace is required, and must be a string`); } @@ -307,7 +302,6 @@ export class SavedObjectsRepository { * @property {Array} [options.fields] * @property {string} [options.namespace] * @property {object} [options.hasReference] - { type, id } - * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes }], total, per_page, page } */ async find(options = {}) { @@ -345,8 +339,7 @@ export class SavedObjectsRepository { ignore: [404], rest_total_hits_as_int: true, body: { - // TODO-VERSION - version: true, + seq_no_primary_term: true, ...getSearchDsl(this._mappings, this._schema, { search, defaultSearchOperator, @@ -387,7 +380,6 @@ export class SavedObjectsRepository { * @param {array} objects - an array ids, or an array of objects containing id and optionally type * @param {object} [options={}] * @property {string} [options.namespace] - * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes }] } * @example * @@ -432,8 +424,7 @@ export class SavedObjectsRepository { id, type, ...time && { updated_at: time }, - // TODO-VERSION - version: doc._version, + version: encodeHitVersion(doc), attributes: doc._source[type], references: doc._source.references || [], migrationVersion: doc._source.migrationVersion, @@ -449,7 +440,6 @@ export class SavedObjectsRepository { * @param {string} id * @param {object} [options={}] * @property {string} [options.namespace] - * // TODO-VERSION * @returns {promise} - { id, type, version, attributes } */ async get(type, id, options = {}) { @@ -477,8 +467,7 @@ export class SavedObjectsRepository { id, type, ...updatedAt && { updated_at: updatedAt }, - // TODO-VERSION - version: response._version, + version: encodeHitVersion(response), attributes: response._source[type], references: response._source.references || [], migrationVersion: response._source.migrationVersion, @@ -491,15 +480,13 @@ export class SavedObjectsRepository { * @param {string} type * @param {string} id * @param {object} [options={}] - * // TODO-VERSION - * @property {integer} options.version - ensures version matches that of persisted object + * @property {string} options.version - ensures version matches that of persisted object * @property {string} [options.namespace] * @property {array} [options.references] - [{ name, type, id }] * @returns {promise} */ async update(type, id, attributes, options = {}) { const { - // TODO-VERSION version, namespace, references = [], @@ -510,8 +497,7 @@ export class SavedObjectsRepository { id: this._serializer.generateRawId(namespace, type, id), type: this._type, index: this._index, - // TODO-VERSION - version, + ...(version && decodeRequestVersion(version)), refresh: 'wait_for', ignore: [404], body: { @@ -532,8 +518,7 @@ export class SavedObjectsRepository { id, type, updated_at: time, - // TODO-VERSION - version: response._version, + version: encodeHitVersion(response), references, attributes }; @@ -609,8 +594,7 @@ export class SavedObjectsRepository { type, updated_at: time, references: response.get._source.references, - // TODO-VERSION - version: response._version, + version: encodeHitVersion(response), attributes: response.get._source[type], }; diff --git a/src/server/saved_objects/service/lib/repository.test.js b/src/server/saved_objects/service/lib/repository.test.js index 7552f7a855901f..e93146e98d788f 100644 --- a/src/server/saved_objects/service/lib/repository.test.js +++ b/src/server/saved_objects/service/lib/repository.test.js @@ -26,6 +26,7 @@ import * as errors from './errors'; import elasticsearch from 'elasticsearch'; import { SavedObjectsSchema } from '../../schema'; import { SavedObjectsSerializer } from '../../serialization'; +import { encodeHitVersion } from './version'; // BEWARE: The SavedObjectClient depends on the implementation details of the SavedObjectsRepository // so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient. @@ -39,6 +40,8 @@ describe('SavedObjectsRepository', () => { let migrator; const mockTimestamp = '2017-08-14T15:49:14.886Z'; const mockTimestampFields = { updated_at: mockTimestamp }; + const mockVersionProps = { _seq_no: 1, _primary_term: 1 }; + const mockVersion = encodeHitVersion(mockVersionProps); const noNamespaceSearchResults = { hits: { total: 4, @@ -47,6 +50,7 @@ describe('SavedObjectsRepository', () => { _type: '_doc', _id: 'index-pattern:logstash-*', _score: 1, + ...mockVersionProps, _source: { type: 'index-pattern', ...mockTimestampFields, @@ -61,6 +65,7 @@ describe('SavedObjectsRepository', () => { _type: '_doc', _id: 'config:6.0.0-alpha1', _score: 1, + ...mockVersionProps, _source: { type: 'config', ...mockTimestampFields, @@ -74,6 +79,7 @@ describe('SavedObjectsRepository', () => { _type: '_doc', _id: 'index-pattern:stocks-*', _score: 1, + ...mockVersionProps, _source: { type: 'index-pattern', ...mockTimestampFields, @@ -88,6 +94,7 @@ describe('SavedObjectsRepository', () => { _type: '_doc', _id: 'globaltype:something', _score: 1, + ...mockVersionProps, _source: { type: 'globaltype', ...mockTimestampFields, @@ -107,6 +114,7 @@ describe('SavedObjectsRepository', () => { _type: '_doc', _id: 'foo-namespace:index-pattern:logstash-*', _score: 1, + ...mockVersionProps, _source: { namespace: 'foo-namespace', type: 'index-pattern', @@ -122,6 +130,7 @@ describe('SavedObjectsRepository', () => { _type: '_doc', _id: 'foo-namespace:config:6.0.0-alpha1', _score: 1, + ...mockVersionProps, _source: { namespace: 'foo-namespace', type: 'config', @@ -136,6 +145,7 @@ describe('SavedObjectsRepository', () => { _type: '_doc', _id: 'foo-namespace:index-pattern:stocks-*', _score: 1, + ...mockVersionProps, _source: { namespace: 'foo-namespace', type: 'index-pattern', @@ -151,6 +161,7 @@ describe('SavedObjectsRepository', () => { _type: '_doc', _id: 'globaltype:something', _score: 1, + ...mockVersionProps, _source: { type: 'globaltype', ...mockTimestampFields, @@ -168,7 +179,6 @@ describe('SavedObjectsRepository', () => { total: 23, deleted: 23, batches: 1, - // TODO-VERSION version_conflicts: 0, noops: 0, retries: { bulk: 0, search: 0 }, @@ -238,8 +248,7 @@ describe('SavedObjectsRepository', () => { callAdminCluster.callsFake((method, params) => ({ _type: '_doc', _id: params.id, - // TODO-VERSION - _version: 2 + ...mockVersionProps, })); }); @@ -272,8 +281,7 @@ describe('SavedObjectsRepository', () => { type: 'index-pattern', id: 'logstash-*', ...mockTimestampFields, - // TODO-VERSION - version: 2, + version: mockVersion, attributes: { title: 'Logstash', }, @@ -474,16 +482,16 @@ describe('SavedObjectsRepository', () => { create: { error: false, _id: '1', - // TODO-VERSION - _version: 1, + _seq_no: 1, + _primary_term: 1, } }, { create: { error: false, _id: '2', - // TODO-VERSION - _version: 1, + _seq_no: 1, + _primary_term: 1, } } ], @@ -527,8 +535,7 @@ describe('SavedObjectsRepository', () => { { id: 'one', type: 'config', - // TODO-VERSION - version: 1, + version: mockVersion, updated_at: mockTimestamp, attributes: { title: 'Test One!!', @@ -538,8 +545,7 @@ describe('SavedObjectsRepository', () => { { id: 'two', type: 'index-pattern', - // TODO-VERSION - version: 1, + version: mockVersion, updated_at: mockTimestamp, attributes: { title: 'Test Two!!', @@ -596,8 +602,7 @@ describe('SavedObjectsRepository', () => { create: { _type: '_doc', _id: 'index-pattern:two', - // TODO-VERSION - _version: 2 + ...mockVersionProps, } }] })); @@ -616,8 +621,7 @@ describe('SavedObjectsRepository', () => { }, { id: 'two', type: 'index-pattern', - // TODO-VERSION - version: 2, + version: mockVersion, ...mockTimestampFields, attributes: { title: 'Test Two' }, references: [], @@ -633,15 +637,13 @@ describe('SavedObjectsRepository', () => { create: { _type: '_doc', _id: 'config:one', - // TODO-VERSION - _version: 2 + ...mockVersionProps } }, { create: { _type: '_doc', _id: 'index-pattern:two', - // TODO-VERSION - _version: 2 + ...mockVersionProps } }] })); @@ -658,16 +660,14 @@ describe('SavedObjectsRepository', () => { { id: 'one', type: 'config', - // TODO-VERSION - version: 2, + version: mockVersion, ...mockTimestampFields, attributes: { title: 'Test One' }, references: [], }, { id: 'two', type: 'index-pattern', - // TODO-VERSION - version: 2, + version: mockVersion, ...mockTimestampFields, attributes: { title: 'Test Two' }, references: [], @@ -965,8 +965,7 @@ describe('SavedObjectsRepository', () => { id: doc._id.replace(/(index-pattern|config|globaltype)\:/, ''), type: doc._source.type, ...mockTimestampFields, - // TODO-VERSION - version: doc._version, + version: mockVersion, attributes: doc._source[doc._source.type], references: [], }); @@ -990,8 +989,7 @@ describe('SavedObjectsRepository', () => { id: doc._id.replace(/(foo-namespace\:)?(index-pattern|config|globaltype)\:/, ''), type: doc._source.type, ...mockTimestampFields, - // TODO-VERSION - version: doc._version, + version: mockVersion, attributes: doc._source[doc._source.type], references: [], }); @@ -1037,8 +1035,7 @@ describe('SavedObjectsRepository', () => { const noNamespaceResult = { _id: 'index-pattern:logstash-*', _type: '_doc', - // TODO-VERSION - _version: 2, + ...mockVersionProps, _source: { type: 'index-pattern', specialProperty: 'specialValue', @@ -1051,8 +1048,7 @@ describe('SavedObjectsRepository', () => { const namespacedResult = { _id: 'foo-namespace:index-pattern:logstash-*', _type: '_doc', - // TODO-VERSION - _version: 2, + ...mockVersionProps, _source: { namespace: 'foo-namespace', type: 'index-pattern', @@ -1081,8 +1077,7 @@ describe('SavedObjectsRepository', () => { id: 'logstash-*', type: 'index-pattern', updated_at: mockTimestamp, - // TODO-VERSION - version: 2, + version: mockVersion, attributes: { title: 'Testing' }, @@ -1098,8 +1093,7 @@ describe('SavedObjectsRepository', () => { id: 'logstash-*', type: 'index-pattern', updated_at: mockTimestamp, - // TODO-VERSION - version: 2, + version: mockVersion, attributes: { title: 'Testing' }, @@ -1228,8 +1222,7 @@ describe('SavedObjectsRepository', () => { _type: '_doc', _id: 'config:good', found: true, - // TODO-VERSION - _version: 2, + ...mockVersionProps, _source: { ...mockTimestampFields, config: { title: 'Test' } } }, { _type: '_doc', @@ -1250,8 +1243,7 @@ describe('SavedObjectsRepository', () => { id: 'good', type: 'config', ...mockTimestampFields, - // TODO-VERSION - version: 2, + version: mockVersion, attributes: { title: 'Test' }, references: [], }); @@ -1266,15 +1258,13 @@ describe('SavedObjectsRepository', () => { describe('#update', () => { const id = 'logstash-*'; const type = 'index-pattern'; - const newVersion = 2; const attributes = { title: 'Testing' }; beforeEach(() => { callAdminCluster.returns(Promise.resolve({ _id: `${type}:${id}`, _type: '_doc', - // TODO-VERSION - _version: newVersion, + ...mockVersionProps, result: 'updated' })); }); @@ -1289,8 +1279,7 @@ describe('SavedObjectsRepository', () => { sinon.assert.calledOnce(migrator.awaitMigration); }); - // TODO-VERSION - it('returns current ES document version', async () => { + it('returns current ES document _seq_no and _primary_term encoded as version', async () => { const response = await savedObjectsRepository.update('index-pattern', 'logstash-*', attributes, { namespace: 'foo-namespace', references: [{ @@ -1303,8 +1292,7 @@ describe('SavedObjectsRepository', () => { id, type, ...mockTimestampFields, - // TODO-VERSION - version: newVersion, + version: mockVersion, attributes, references: [{ name: 'ref_0', @@ -1314,20 +1302,23 @@ describe('SavedObjectsRepository', () => { }); }); - // TODO-VERSION it('accepts version', async () => { await savedObjectsRepository.update( type, id, { title: 'Testing' }, - // TODO-VERSION - { version: newVersion - 1 } + { + version: encodeHitVersion({ + _seq_no: 100, + _primary_term: 200 + }) + } ); sinon.assert.calledOnce(callAdminCluster); sinon.assert.calledWithExactly(callAdminCluster, sinon.match.string, sinon.match({ - // TODO-VERSION - version: newVersion - 1 + if_seq_no: 100, + if_primary_term: 200, })); }); @@ -1347,8 +1338,6 @@ describe('SavedObjectsRepository', () => { sinon.assert.calledWithExactly(callAdminCluster, 'update', { type: '_doc', id: 'foo-namespace:index-pattern:logstash-*', - // TODO-VERSION - version: undefined, body: { doc: { updated_at: mockTimestamp, @@ -1383,8 +1372,6 @@ describe('SavedObjectsRepository', () => { sinon.assert.calledWithExactly(callAdminCluster, 'update', { type: '_doc', id: 'index-pattern:logstash-*', - // TODO-VERSION - version: undefined, body: { doc: { updated_at: mockTimestamp, @@ -1420,8 +1407,6 @@ describe('SavedObjectsRepository', () => { sinon.assert.calledWithExactly(callAdminCluster, 'update', { type: '_doc', id: 'globaltype:foo', - // TODO-VERSION - version: undefined, body: { doc: { updated_at: mockTimestamp, @@ -1447,8 +1432,7 @@ describe('SavedObjectsRepository', () => { callAdminCluster.callsFake((method, params) => ({ _type: '_doc', _id: params.id, - // TODO-VERSION - _version: 2, + ...mockVersionProps, _index: '.kibana', get: { found: true, @@ -1468,8 +1452,7 @@ describe('SavedObjectsRepository', () => { callAdminCluster.callsFake((method, params) => ({ _type: '_doc', _id: params.id, - // TODO-VERSION - _version: 2, + ...mockVersionProps, _index: '.kibana', get: { found: true, @@ -1498,8 +1481,7 @@ describe('SavedObjectsRepository', () => { type: 'config', id: '6.0.0-alpha1', ...mockTimestampFields, - // TODO-VERSION - version: 2, + version: mockVersion, attributes: { buildNum: 8468, defaultIndex: 'logstash-*' @@ -1572,8 +1554,7 @@ describe('SavedObjectsRepository', () => { callAdminCluster.callsFake((method, params) => ({ _type: '_doc', _id: params.id, - // TODO-VERSION - _version: 2, + ...mockVersionProps, _index: '.kibana', get: { found: true, diff --git a/src/server/saved_objects/service/lib/version.ts b/src/server/saved_objects/service/lib/version.ts new file mode 100644 index 00000000000000..5d04d914ffcefd --- /dev/null +++ b/src/server/saved_objects/service/lib/version.ts @@ -0,0 +1,90 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { createInvalidVersionError } from './errors'; + +const decodeBase64 = (base64: string) => Buffer.from(base64, 'base64').toString('utf8'); +const encodeBase64 = (utf8: string) => Buffer.from(utf8, 'utf8').toString('base64'); + +/** + * Encode the sequence params into an "opaque" version string + * that can be used in the saved object API in place of numeric + * version numbers + */ +export function encodeVersion(seqNo: number, primaryTerm: number) { + if (!Number.isInteger(primaryTerm)) { + throw new TypeError('_primary_term from elasticsearch must be an integer'); + } + + if (!Number.isInteger(seqNo)) { + throw new TypeError('_seq_no from elasticsearch must be an integer'); + } + + return encodeBase64(JSON.stringify([seqNo, primaryTerm])); +} + +/** + * Helper for encoding a version from a "hit" (hits.hits[#] from _search) or + * "doc" (body from GET, update, etc) object + */ +export function encodeHitVersion(response: { _seq_no: number; _primary_term: number }) { + return encodeVersion(response._seq_no, response._primary_term); +} + +/** + * Decode the "opaque" version string to the sequence params we + * can use to activate optimistic concurrency in Elasticsearch + */ +export function decodeVersion(version?: string) { + try { + if (typeof version !== 'string') { + throw new TypeError(); + } + + const seqParams = JSON.parse(decodeBase64(version)) as [number, number]; + + if ( + !seqParams || + seqParams.length !== 2 || + !Number.isInteger(seqParams[0]) || + !Number.isInteger(seqParams[1]) + ) { + throw new TypeError(); + } + + return { + _seq_no: seqParams[0], + _primary_term: seqParams[1], + }; + } catch (_) { + throw createInvalidVersionError(version); + } +} + +/** + * Helper for decoding version to request params that are driven + * by the version info + */ +export function decodeRequestVersion(version?: string) { + const decoded = decodeVersion(version); + return { + if_seq_no: decoded._seq_no, + if_primary_term: decoded._primary_term, + }; +} diff --git a/src/server/saved_objects/service/saved_objects_client.js b/src/server/saved_objects/service/saved_objects_client.js index b05c13ce67397e..a18881ad09d41a 100644 --- a/src/server/saved_objects/service/saved_objects_client.js +++ b/src/server/saved_objects/service/saved_objects_client.js @@ -103,7 +103,6 @@ export class SavedObjectsClient { * @property {string} [options.id] - force id on creation, not recommended * @property {boolean} [options.overwrite=false] * @property {string} [options.namespace] - * // TODO-VERSION * @returns {promise} - { id, type, version, attributes } */ async create(type, attributes = {}, options = {}) { @@ -117,7 +116,6 @@ export class SavedObjectsClient { * @param {object} [options={}] * @property {boolean} [options.overwrite=false] - overwrites existing documents * @property {string} [options.namespace] - * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes, error: { message } }]} */ async bulkCreate(objects, options = {}) { @@ -151,7 +149,6 @@ export class SavedObjectsClient { * @property {Array} [options.fields] * @property {string} [options.namespace] * @property {object} [options.hasReference] - { type, id } - * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes }], total, per_page, page } */ async find(options = {}) { @@ -164,7 +161,6 @@ export class SavedObjectsClient { * @param {array} objects - an array ids, or an array of objects containing id and optionally type * @param {object} [options={}] * @property {string} [options.namespace] - * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes }] } * @example * @@ -184,7 +180,6 @@ export class SavedObjectsClient { * @param {string} id * @param {object} [options={}] * @property {string} [options.namespace] - * // TODO-VERSION * @returns {promise} - { id, type, version, attributes } */ async get(type, id, options = {}) { @@ -197,7 +192,6 @@ export class SavedObjectsClient { * @param {string} type * @param {string} id * @param {object} [options={}] - * // TODO-VERSION * @property {integer} options.version - ensures version matches that of persisted object * @property {string} [options.namespace] * @returns {promise} diff --git a/src/ui/public/saved_objects/__tests__/saved_object.js b/src/ui/public/saved_objects/__tests__/saved_object.js index 6ad5f102a3f489..4d8357a8bc76b0 100644 --- a/src/ui/public/saved_objects/__tests__/saved_object.js +++ b/src/ui/public/saved_objects/__tests__/saved_object.js @@ -46,10 +46,7 @@ describe('SavedObject', () => { const version = 2; const client = sinon.stub(); - // TODO-VERSION const savedObject = new SavedObject(client, { version }); - - // TODO-VERSION expect(savedObject._version).to.be(version); }); }); diff --git a/src/ui/public/saved_objects/__tests__/saved_objects_client.test.js b/src/ui/public/saved_objects/__tests__/saved_objects_client.test.js index fa39e694b5a6a3..6819e9b7c4ad50 100644 --- a/src/ui/public/saved_objects/__tests__/saved_objects_client.test.js +++ b/src/ui/public/saved_objects/__tests__/saved_objects_client.test.js @@ -29,8 +29,7 @@ describe('SavedObjectsClient', () => { id: 'AVwSwFxtcMV38qjDZoQg', type: 'config', attributes: { title: 'Example title' }, - // TODO-VERSION - version: 2 + version: 'foo' }; let kfetchStub; @@ -229,10 +228,8 @@ describe('SavedObjectsClient', () => { test('makes HTTP call', () => { const attributes = { foo: 'Foo', bar: 'Bar' }; - // TODO-VERSION - const body = { attributes, version: 2 }; - // TODO-VERSION - const options = { version: 2 }; + const body = { attributes, version: 'foo' }; + const options = { version: 'foo' }; savedObjectsClient.update('index-pattern', 'logstash-*', attributes, options); sinon.assert.calledOnce(kfetchStub); diff --git a/src/ui/public/saved_objects/saved_object.js b/src/ui/public/saved_objects/saved_object.js index 931bddb4cdcefe..ed3bbfe9b0fb1a 100644 --- a/src/ui/public/saved_objects/saved_object.js +++ b/src/ui/public/saved_objects/saved_object.js @@ -20,14 +20,12 @@ import _ from 'lodash'; export class SavedObject { - // TODO-VERSION constructor(client, { id, type, version, attributes, error, migrationVersion, references } = {}) { this._client = client; this.id = id; this.type = type; this.attributes = attributes || {}; this.references = references || []; - // TODO-VERSION this._version = version; this.migrationVersion = migrationVersion; if (error) { diff --git a/src/ui/public/saved_objects/saved_objects_client.js b/src/ui/public/saved_objects/saved_objects_client.js index a7af6da0c193e0..0ee4c2ff47ad32 100644 --- a/src/ui/public/saved_objects/saved_objects_client.js +++ b/src/ui/public/saved_objects/saved_objects_client.js @@ -52,7 +52,6 @@ export class SavedObjectsClient { * @property {boolean} [options.overwrite=false] * @property {object} [options.migrationVersion] * @property {array} [options.references] [{ name, type, id }] - * // TODO-VERSION * @returns {promise} - SavedObject({ id, type, version, attributes }) */ create = (type, attributes = {}, options = {}) => { @@ -90,7 +89,6 @@ export class SavedObjectsClient { * @param {array} objects - [{ type, id, attributes, references, migrationVersion }] * @param {object} [options={}] * @property {boolean} [options.overwrite=false] - * // TODO-VERSION * @returns {promise} - { savedObjects: [{ id, type, version, attributes, error: { message } }]} */ bulkCreate = (objects = [], options = {}) => { @@ -131,7 +129,6 @@ export class SavedObjectsClient { * @property {integer} [options.perPage=20] * @property {array} options.fields * @property {object} [options.hasReference] - { type, id } - * // TODO-VERSION * @returns {promise} - { savedObjects: [ SavedObject({ id, type, version, attributes }) ]} */ find = (options = {}) => { @@ -149,7 +146,6 @@ export class SavedObjectsClient { * * @param {string} type * @param {string} id - * // TODO-VERSION * @returns {promise} - SavedObject({ id, type, version, attributes }) */ get = (type, id) => { @@ -167,7 +163,6 @@ export class SavedObjectsClient { * Returns an array of objects by id * * @param {array} objects - an array ids, or an array of objects containing id and optionally type - * // TODO-VERSION * @returns {promise} - { savedObjects: [ SavedObject({ id, type, version, attributes }) ] } * @example * @@ -193,13 +188,11 @@ export class SavedObjectsClient { * @param {string} id * @param {object} attributes * @param {object} options - * // TODO-VERSION * @prop {integer} options.version - ensures version matches that of persisted object * @prop {object} options.migrationVersion - The optional migrationVersion of this document * @prop {array} option.references - the references of the saved object * @returns {promise} */ - // TODO-VERSION update(type, id, attributes, { version, migrationVersion, references } = {}) { if (!type || !id || !attributes) { return Promise.reject(new Error('requires type, id and attributes')); @@ -210,7 +203,6 @@ export class SavedObjectsClient { attributes, migrationVersion, references, - // TODO-VERSION version }; From 62d3a7331bf863eb697b2f5658d16620737ee802 Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 03:16:42 -0800 Subject: [PATCH 04/21] [spaces] update spaces integration test fixtures --- .../elasticsearch/lib/__tests__/health_check.js | 2 -- .../public/courier/saved_object/__tests__/saved_object.js | 1 - src/ui/public/doc_table/doc_table.html | 2 -- .../common/suites/bulk_create.ts | 6 ++---- .../saved_object_api_integration/common/suites/bulk_get.ts | 3 --- .../saved_object_api_integration/common/suites/create.ts | 6 ++---- .../test/saved_object_api_integration/common/suites/find.ts | 6 ++---- .../test/saved_object_api_integration/common/suites/get.ts | 2 -- .../saved_object_api_integration/common/suites/update.ts | 6 ++---- 9 files changed, 8 insertions(+), 26 deletions(-) diff --git a/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js b/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js index 73ef4090c0a6e4..ce382729572ccb 100644 --- a/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js +++ b/src/legacy/core_plugins/elasticsearch/lib/__tests__/health_check.js @@ -61,8 +61,6 @@ describe('plugins/elasticsearch', () => { cluster = { callWithInternalUser: sinon.stub() }; cluster.callWithInternalUser.withArgs('index', sinon.match.any).returns(Promise.resolve()); - // TODO-VERSION - cluster.callWithInternalUser.withArgs('create', sinon.match.any).returns(Promise.resolve({ _id: '1', _version: 1 })); cluster.callWithInternalUser.withArgs('mget', sinon.match.any).returns(Promise.resolve({ ok: true })); cluster.callWithInternalUser.withArgs('get', sinon.match.any).returns(Promise.resolve({ found: false })); cluster.callWithInternalUser.withArgs('search', sinon.match.any).returns(Promise.resolve({ hits: { hits: [] } })); diff --git a/src/ui/public/courier/saved_object/__tests__/saved_object.js b/src/ui/public/courier/saved_object/__tests__/saved_object.js index f61300bebf8e84..0b19c8f608be1b 100644 --- a/src/ui/public/courier/saved_object/__tests__/saved_object.js +++ b/src/ui/public/courier/saved_object/__tests__/saved_object.js @@ -42,7 +42,6 @@ describe('Saved Object', function () { * that can be used to stub es calls. * @param indexPatternId * @param additionalOptions - object that will be assigned to the mocked doc response. - // TODO-VERSION * @returns {{attributes: {}, type: string, id: *, _version: integer}} */ function getMockedDocResponse(indexPatternId, additionalOptions = {}) { diff --git a/src/ui/public/doc_table/doc_table.html b/src/ui/public/doc_table/doc_table.html index e05ceafe9ce5a9..c035a36dfe907c 100644 --- a/src/ui/public/doc_table/doc_table.html +++ b/src/ui/public/doc_table/doc_table.html @@ -37,7 +37,6 @@ on-remove-column="onRemoveColumn" > - - ) { type: 'globaltype', id: `8121a00-8efd-21e7-1cb3-34ab966434445`, - // TODO-VERSION - version: 1, + version: resp.body.saved_objects[0].version, attributes: { name: 'My favorite global object', }, @@ -97,8 +96,7 @@ export function findTestSuiteFactory(esArchiver: any, supertest: SuperTest) { type: 'visualization', id: `${getIdPrefix(spaceId)}dd7caf20-9efd-11e7-acb3-3dab96693fab`, - // TODO-VERSION - version: 1, + version: resp.body.saved_objects[0].version, attributes: { title: 'Count of requests', }, diff --git a/x-pack/test/saved_object_api_integration/common/suites/get.ts b/x-pack/test/saved_object_api_integration/common/suites/get.ts index 71109810f5afae..1cc36b411c61a7 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/get.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/get.ts @@ -65,7 +65,6 @@ export function getTestSuiteFactory(esArchiver: any, supertest: SuperTest) id: `${notSpaceAwareId}`, type: 'globaltype', updated_at: '2017-09-21T18:59:16.270Z', - // TODO-VERSION version: resp.body.version, attributes: { name: 'My favorite global object', @@ -100,7 +99,6 @@ export function getTestSuiteFactory(esArchiver: any, supertest: SuperTest) visualization: '7.0.0', }, updated_at: '2017-09-21T18:51:23.794Z', - // TODO-VERSION version: resp.body.version, attributes: { title: 'Count of requests', diff --git a/x-pack/test/saved_object_api_integration/common/suites/update.ts b/x-pack/test/saved_object_api_integration/common/suites/update.ts index d67142c2de38d7..7fa534e142b3dc 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/update.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/update.ts @@ -74,8 +74,7 @@ export function updateTestSuiteFactory(esArchiver: any, supertest: SuperTest Date: Sat, 2 Feb 2019 03:30:15 -0800 Subject: [PATCH 05/21] [apiIntegration] update saved object api fixtures --- test/api_integration/apis/saved_objects/bulk_create.js | 9 +++------ test/api_integration/apis/saved_objects/bulk_get.js | 2 -- test/api_integration/apis/saved_objects/create.js | 6 ++---- test/api_integration/apis/saved_objects/find.js | 3 +-- test/api_integration/apis/saved_objects/get.js | 1 - test/api_integration/apis/saved_objects/update.js | 3 +-- 6 files changed, 7 insertions(+), 17 deletions(-) diff --git a/test/api_integration/apis/saved_objects/bulk_create.js b/test/api_integration/apis/saved_objects/bulk_create.js index 7f29e01f9129c4..44aaaf0fa55b18 100644 --- a/test/api_integration/apis/saved_objects/bulk_create.js +++ b/test/api_integration/apis/saved_objects/bulk_create.js @@ -66,8 +66,7 @@ export default function ({ getService }) { type: 'dashboard', id: 'a01b2f57-fcfd-4864-b735-09e28f0d815e', updated_at: resp.body.saved_objects[1].updated_at, - // TODO-VERSION - version: 1, + version: 'WzgsMV0=', attributes: { title: 'A great new dashboard' }, @@ -100,8 +99,7 @@ export default function ({ getService }) { type: 'visualization', id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', updated_at: resp.body.saved_objects[0].updated_at, - // TODO-VERSION - version: 1, + version: 'WzAsMV0=', attributes: { title: 'An existing visualization' }, @@ -111,8 +109,7 @@ export default function ({ getService }) { type: 'dashboard', id: 'a01b2f57-fcfd-4864-b735-09e28f0d815e', updated_at: resp.body.saved_objects[1].updated_at, - // TODO-VERSION - version: 1, + version: 'WzEsMV0=', attributes: { title: 'A great new dashboard' }, diff --git a/test/api_integration/apis/saved_objects/bulk_get.js b/test/api_integration/apis/saved_objects/bulk_get.js index d02dd602654f27..da208a5cbe70ad 100644 --- a/test/api_integration/apis/saved_objects/bulk_get.js +++ b/test/api_integration/apis/saved_objects/bulk_get.js @@ -59,7 +59,6 @@ export default function ({ getService }) { }, type: 'visualization', updated_at: '2017-09-21T18:51:23.794Z', - // TODO-VERSION version: resp.body.saved_objects[0].version, attributes: { title: 'Count of requests', @@ -91,7 +90,6 @@ export default function ({ getService }) { id: '7.0.0-alpha1', type: 'config', updated_at: '2017-09-21T18:49:16.302Z', - // TODO-VERSION version: resp.body.saved_objects[2].version, attributes: { buildNum: 8467, diff --git a/test/api_integration/apis/saved_objects/create.js b/test/api_integration/apis/saved_objects/create.js index 60a457438c458c..17b4fc55fbb4e8 100644 --- a/test/api_integration/apis/saved_objects/create.js +++ b/test/api_integration/apis/saved_objects/create.js @@ -51,8 +51,7 @@ export default function ({ getService }) { visualization: '7.0.0' }, updated_at: resp.body.updated_at, - // TODO-VERSION - version: 1, + version: 'WzgsMV0=', attributes: { title: 'My favorite vis' }, @@ -97,8 +96,7 @@ export default function ({ getService }) { visualization: '7.0.0' }, updated_at: resp.body.updated_at, - // TODO-VERSION - version: 1, + version: 'WzAsMV0=', attributes: { title: 'My favorite vis' }, diff --git a/test/api_integration/apis/saved_objects/find.js b/test/api_integration/apis/saved_objects/find.js index a9ffb5cc060f28..3d291867aea6d0 100644 --- a/test/api_integration/apis/saved_objects/find.js +++ b/test/api_integration/apis/saved_objects/find.js @@ -42,8 +42,7 @@ export default function ({ getService }) { { type: 'visualization', id: 'dd7caf20-9efd-11e7-acb3-3dab96693fab', - // TODO-VERSION - version: 1, + version: 'WzIsMV0=', attributes: { 'title': 'Count of requests' }, diff --git a/test/api_integration/apis/saved_objects/get.js b/test/api_integration/apis/saved_objects/get.js index 4c2ab262fdc7f0..0734918f5f3e4a 100644 --- a/test/api_integration/apis/saved_objects/get.js +++ b/test/api_integration/apis/saved_objects/get.js @@ -41,7 +41,6 @@ export default function ({ getService }) { }, type: 'visualization', updated_at: '2017-09-21T18:51:23.794Z', - // TODO-VERSION version: resp.body.version, migrationVersion: { visualization: '7.0.0', diff --git a/test/api_integration/apis/saved_objects/update.js b/test/api_integration/apis/saved_objects/update.js index 604fa38177450c..4e56a9f1208818 100644 --- a/test/api_integration/apis/saved_objects/update.js +++ b/test/api_integration/apis/saved_objects/update.js @@ -48,8 +48,7 @@ export default function ({ getService }) { id: resp.body.id, type: 'visualization', updated_at: resp.body.updated_at, - // TODO-VERSION - version: 2, + version: 'WzgsMV0=', attributes: { title: 'My second favorite vis' }, From e55ab0a01e32b1b8a56a270093ac951f78206c46 Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 03:30:50 -0800 Subject: [PATCH 06/21] [saveObjects/types] fix version type --- src/server/saved_objects/service/saved_objects_client.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server/saved_objects/service/saved_objects_client.d.ts b/src/server/saved_objects/service/saved_objects_client.d.ts index a58cec023b3359..6f3578acb6e4d8 100644 --- a/src/server/saved_objects/service/saved_objects_client.d.ts +++ b/src/server/saved_objects/service/saved_objects_client.d.ts @@ -58,7 +58,7 @@ export interface FindResponse { } export interface UpdateOptions extends BaseOptions { - version?: number; + version?: string; } export interface BulkGetObject { @@ -78,7 +78,7 @@ export interface SavedObjectAttributes { export interface SavedObject { id: string; type: string; - version?: number; + version?: string; updated_at?: string; error?: { message: string; From c528f78a34cca2576610286bf3a7b572094c4a36 Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 04:15:00 -0800 Subject: [PATCH 07/21] update several uses of savedObjects versions to expect strings --- .../infra/public/graphql/introspection.json | 22 ++++++------- x-pack/plugins/infra/public/graphql/types.ts | 2 +- .../server/graphql/sources/schema.gql.ts | 2 +- x-pack/plugins/infra/server/graphql/types.ts | 6 ++-- .../infra/server/lib/sources/sources.ts | 2 -- .../plugins/infra/server/lib/sources/types.ts | 3 +- .../spaces_saved_objects_client.ts | 8 +---- .../lib/reindexing/reindex_actions.test.ts | 9 ++---- .../server/lib/reindexing/reindex_actions.ts | 3 -- .../api_integration/apis/infra/sources.ts | 32 +++++++------------ 10 files changed, 33 insertions(+), 56 deletions(-) diff --git a/x-pack/plugins/infra/public/graphql/introspection.json b/x-pack/plugins/infra/public/graphql/introspection.json index e64b567aa88efb..356bc03f19a8b3 100644 --- a/x-pack/plugins/infra/public/graphql/introspection.json +++ b/x-pack/plugins/infra/public/graphql/introspection.json @@ -89,7 +89,7 @@ "name": "version", "description": "The version number the source configuration was last persisted with", "args": [], - "type": { "kind": "SCALAR", "name": "Float", "ofType": null }, + "type": { "kind": "SCALAR", "name": "String", "ofType": null }, "isDeprecated": false, "deprecationReason": null }, @@ -430,6 +430,16 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "SCALAR", + "name": "String", + "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, { "kind": "SCALAR", "name": "Float", @@ -511,16 +521,6 @@ "enumValues": null, "possibleTypes": null }, - { - "kind": "SCALAR", - "name": "String", - "description": "The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text.", - "fields": null, - "inputFields": null, - "interfaces": null, - "enumValues": null, - "possibleTypes": null - }, { "kind": "OBJECT", "name": "InfraSourceFields", diff --git a/x-pack/plugins/infra/public/graphql/types.ts b/x-pack/plugins/infra/public/graphql/types.ts index d96719aef00591..e490fdb7477c37 100644 --- a/x-pack/plugins/infra/public/graphql/types.ts +++ b/x-pack/plugins/infra/public/graphql/types.ts @@ -19,7 +19,7 @@ export interface InfraSource { /** The id of the source */ id: string; /** The version number the source configuration was last persisted with */ - version?: number | null; + version?: string | null; /** The timestamp the source configuration was last persisted at */ updatedAt?: number | null; /** The raw configuration of the source */ diff --git a/x-pack/plugins/infra/server/graphql/sources/schema.gql.ts b/x-pack/plugins/infra/server/graphql/sources/schema.gql.ts index b567ccd52dfc27..dd87e9ecb34cc4 100644 --- a/x-pack/plugins/infra/server/graphql/sources/schema.gql.ts +++ b/x-pack/plugins/infra/server/graphql/sources/schema.gql.ts @@ -12,7 +12,7 @@ export const sourcesSchema = gql` "The id of the source" id: ID! "The version number the source configuration was last persisted with" - version: Float + version: String "The timestamp the source configuration was last persisted at" updatedAt: Float "The raw configuration of the source" diff --git a/x-pack/plugins/infra/server/graphql/types.ts b/x-pack/plugins/infra/server/graphql/types.ts index 69332026338569..d1ffd4958b2607 100644 --- a/x-pack/plugins/infra/server/graphql/types.ts +++ b/x-pack/plugins/infra/server/graphql/types.ts @@ -47,7 +47,7 @@ export interface InfraSource { /** The id of the source */ id: string; /** The version number the source configuration was last persisted with */ - version?: number | null; + version?: string | null; /** The timestamp the source configuration was last persisted at */ updatedAt?: number | null; /** The raw configuration of the source */ @@ -606,7 +606,7 @@ export namespace InfraSourceResolvers { /** The id of the source */ id?: IdResolver; /** The version number the source configuration was last persisted with */ - version?: VersionResolver; + version?: VersionResolver; /** The timestamp the source configuration was last persisted at */ updatedAt?: UpdatedAtResolver; /** The raw configuration of the source */ @@ -635,7 +635,7 @@ export namespace InfraSourceResolvers { Context >; export type VersionResolver< - R = number | null, + R = string | null, Parent = InfraSource, Context = InfraContext > = Resolver; diff --git a/x-pack/plugins/infra/server/lib/sources/sources.ts b/x-pack/plugins/infra/server/lib/sources/sources.ts index 124df11c9e10b6..8957e83c5a0357 100644 --- a/x-pack/plugins/infra/server/lib/sources/sources.ts +++ b/x-pack/plugins/infra/server/lib/sources/sources.ts @@ -129,7 +129,6 @@ export class InfraSources { sourceId, { ...updatedConfigurationAttributes }, { - // TODO-VERSION version, } ) @@ -205,7 +204,6 @@ const convertSavedObjectToSavedSourceConfiguration = (savedObject: unknown) => InfraSavedSourceConfigurationRuntimeType.decode(savedObject) .map(savedSourceConfiguration => ({ id: savedSourceConfiguration.id, - // TODO-VERSION version: savedSourceConfiguration.version, updatedAt: savedSourceConfiguration.updated_at, configuration: savedSourceConfiguration.attributes, diff --git a/x-pack/plugins/infra/server/lib/sources/types.ts b/x-pack/plugins/infra/server/lib/sources/types.ts index 17db11b6b2b591..a70062fb3ddf56 100644 --- a/x-pack/plugins/infra/server/lib/sources/types.ts +++ b/x-pack/plugins/infra/server/lib/sources/types.ts @@ -51,8 +51,7 @@ export const InfraSavedSourceConfigurationRuntimeType = runtimeTypes.intersectio attributes: PartialInfraSourceConfigurationRuntimeType, }), runtimeTypes.partial({ - // TODO-VERSION - version: runtimeTypes.number, + version: runtimeTypes.string, updated_at: TimestampFromString, }), ]); diff --git a/x-pack/plugins/spaces/server/lib/saved_objects_client/spaces_saved_objects_client.ts b/x-pack/plugins/spaces/server/lib/saved_objects_client/spaces_saved_objects_client.ts index 142c80b2d5be1f..d205c21c880e96 100644 --- a/x-pack/plugins/spaces/server/lib/saved_objects_client/spaces_saved_objects_client.ts +++ b/x-pack/plugins/spaces/server/lib/saved_objects_client/spaces_saved_objects_client.ts @@ -82,7 +82,6 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient { * @property {string} [options.id] - force id on creation, not recommended * @property {boolean} [options.overwrite=false] * @property {string} [options.namespace] - * // TODO-VERSION * @returns {promise} - { id, type, version, attributes } */ public async create( @@ -106,7 +105,6 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient { * @param {object} [options={}] * @property {boolean} [options.overwrite=false] - overwrites existing documents * @property {string} [options.namespace] - * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes, error: { message } }]} */ public async bulkCreate(objects: BulkCreateObject[], options: BaseOptions = {}) { @@ -152,7 +150,6 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient { * @property {Array} [options.fields] * @property {string} [options.namespace] * @property {object} [options.hasReference] - { type, id } - * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes }], total, per_page, page } */ public async find(options: FindOptions = {}) { @@ -177,7 +174,6 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient { * @param {array} objects - an array ids, or an array of objects containing id and optionally type * @param {object} [options={}] * @property {string} [options.namespace] - * // TODO-VERSION * @returns {promise} - { saved_objects: [{ id, type, version, attributes }] } * @example * @@ -203,7 +199,6 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient { * @param {string} id * @param {object} [options={}] * @property {string} [options.namespace] - * // TODO-VERSION * @returns {promise} - { id, type, version, attributes } */ public async get(type: string, id: string, options: BaseOptions = {}) { @@ -222,8 +217,7 @@ export class SpacesSavedObjectsClient implements SavedObjectsClient { * @param {string} type * @param {string} id * @param {object} [options={}] - * // TODO-VERSION - * @property {integer} options.version - ensures version matches that of persisted object + * @property {string} options.version - ensures version matches that of persisted object * @property {string} [options.namespace] * @returns {promise} */ diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts index e4d8a6bebeb1ca..9e030c07f2d5ad 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts @@ -91,8 +91,7 @@ describe('ReindexActions', () => { type: REINDEX_OP_TYPE, id: '9', attributes: { indexName: 'hi', locked: moment().format() }, - // TODO-VERSION - version: 1, + version: 'foo', } as ReindexSavedObject, { newIndexName: 'test' } ); @@ -102,8 +101,7 @@ describe('ReindexActions', () => { expect(args[1]).toEqual('9'); expect(args[2].indexName).toEqual('hi'); expect(args[2].newIndexName).toEqual('test'); - // TODO-VERSION - expect(args[3]).toEqual({ version: 1 }); + expect(args[3]).toEqual({ version: 'foo' }); }); it('throws if the reindexOp is not locked', async () => { @@ -113,8 +111,7 @@ describe('ReindexActions', () => { type: REINDEX_OP_TYPE, id: '10', attributes: { indexName: 'hi', locked: null }, - // TODO-VERSION - version: 1, + version: 'foo', } as ReindexSavedObject, { newIndexName: 'test' } ) diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts index fde9e98d3ae644..30fe268c639535 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.ts @@ -158,7 +158,6 @@ export const reindexActionsFactory = ( REINDEX_OP_TYPE, reindexOp.id, { ...reindexOp.attributes, locked: moment().format() }, - // TODO-VERSION { version: reindexOp.version } ); }; @@ -168,7 +167,6 @@ export const reindexActionsFactory = ( REINDEX_OP_TYPE, reindexOp.id, { ...reindexOp.attributes, locked: null }, - // TODO-VERSION { version: reindexOp.version } ); }; @@ -200,7 +198,6 @@ export const reindexActionsFactory = ( const newAttrs = { ...reindexOp.attributes, locked: moment().format(), ...attrs }; return client.update(REINDEX_OP_TYPE, reindexOp.id, newAttrs, { - // TODO-VERSION version: reindexOp.version, }); }, diff --git a/x-pack/test/api_integration/apis/infra/sources.ts b/x-pack/test/api_integration/apis/infra/sources.ts index 06c081188e3813..8158921d4d0654 100644 --- a/x-pack/test/api_integration/apis/infra/sources.ts +++ b/x-pack/test/api_integration/apis/infra/sources.ts @@ -69,11 +69,10 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); - // TODO-VERSION const { version, updatedAt, configuration, status } = response.data && response.data.createSource.source; - expect(version).to.be.greaterThan(0); + expect(version).to.be.a('string'); expect(updatedAt).to.be.greaterThan(0); expect(configuration.name).to.be('NAME'); expect(configuration.description).to.be('DESCRIPTION'); @@ -99,11 +98,10 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); - // TODO-VERSION const { version, updatedAt, configuration, status } = response.data && response.data.createSource.source; - expect(version).to.be.greaterThan(0); + expect(version).to.be.a('string'); expect(updatedAt).to.be.greaterThan(0); expect(configuration.name).to.be('NAME'); expect(configuration.description).to.be(''); @@ -162,10 +160,9 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); - // TODO-VERSION const { version } = creationResponse.data && creationResponse.data.createSource.source; - expect(version).to.be.greaterThan(0); + expect(version).to.be.a('string'); const deletionResponse = await client.mutate({ mutation: deleteSourceMutation, @@ -192,11 +189,10 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); - // TODO-VERSION const { version: initialVersion, updatedAt: createdAt } = creationResponse.data && creationResponse.data.createSource.source; - expect(initialVersion).to.be.greaterThan(0); + expect(initialVersion).to.be.a('string'); expect(createdAt).to.be.greaterThan(0); const updateResponse = await client.mutate({ @@ -233,11 +229,11 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); - // TODO-VERSION const { version, updatedAt, configuration, status } = updateResponse.data && updateResponse.data.updateSource.source; - expect(version).to.be.greaterThan(initialVersion); + expect(version).to.be.a('string'); + expect(version).to.not.be(initialVersion); expect(updatedAt).to.be.greaterThan(createdAt); expect(configuration.name).to.be('UPDATED_NAME'); expect(configuration.description).to.be('UPDATED_DESCRIPTION'); @@ -263,11 +259,10 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); - // TODO-VERSION const { version: initialVersion, updatedAt: createdAt } = creationResponse.data && creationResponse.data.createSource.source; - expect(initialVersion).to.be.greaterThan(0); + expect(initialVersion).to.be.a('string'); expect(createdAt).to.be.greaterThan(0); const updateResponse = await client.mutate({ @@ -284,11 +279,11 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); - // TODO-VERSION const { version, updatedAt, configuration, status } = updateResponse.data && updateResponse.data.updateSource.source; - expect(version).to.be.greaterThan(initialVersion); + expect(version).to.be.a('string'); + expect(version).to.not.be(initialVersion); expect(updatedAt).to.be.greaterThan(createdAt); expect(configuration.metricAlias).to.be('metricbeat-**'); expect(configuration.logAlias).to.be('filebeat-*'); @@ -307,11 +302,10 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); - // TODO-VERSION const { version: initialVersion, updatedAt: createdAt } = creationResponse.data && creationResponse.data.createSource.source; - expect(initialVersion).to.be.greaterThan(0); + expect(initialVersion).to.be.a('string'); expect(createdAt).to.be.greaterThan(0); const updateResponse = await client.mutate({ @@ -328,11 +322,11 @@ const sourcesTests: KbnTestProvider = ({ getService }) => { }, }); - // TODO-VERSION const { version, updatedAt, configuration } = updateResponse.data && updateResponse.data.updateSource.source; - expect(version).to.be.greaterThan(initialVersion); + expect(version).to.be.a('string'); + expect(version).to.not.be(initialVersion); expect(updatedAt).to.be.greaterThan(createdAt); expect(configuration.fields.container).to.be('UPDATED_CONTAINER'); expect(configuration.fields.host).to.be('host.name'); @@ -352,7 +346,6 @@ const createSourceMutation = gql` createSource(id: $sourceId, source: $source) { source { id - // TODO-VERSION version updatedAt configuration { @@ -390,7 +383,6 @@ const updateSourceMutation = gql` updateSource(id: $sourceId, changes: $changes) { source { id - // TODO-VERSION version updatedAt configuration { From 35343fc1493694bf91a2b858bf34d829d0eef43c Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 04:18:11 -0800 Subject: [PATCH 08/21] disable --bail --- tasks/config/run.js | 8 ++++---- tasks/function_test_groups.js | 2 +- test/scripts/jenkins_xpack_ci_group.sh | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tasks/config/run.js b/tasks/config/run.js index 4d2c1a11d34529..1985392d8f9c2e 100644 --- a/tasks/config/run.js +++ b/tasks/config/run.js @@ -183,7 +183,7 @@ module.exports = function (grunt) { 'scripts/functional_tests', '--config', 'test/api_integration/config.js', '--esFrom', esFrom, - '--bail', + // '--bail', '--debug', ], }, @@ -195,7 +195,7 @@ module.exports = function (grunt) { '--config', 'test/server_integration/http/ssl/config.js', '--config', 'test/server_integration/http/ssl_redirect/config.js', '--esFrom', esFrom, - '--bail', + // '--bail', '--debug', '--kibana-install-dir', KIBANA_INSTALL_DIR, ], @@ -207,7 +207,7 @@ module.exports = function (grunt) { 'scripts/functional_tests', '--config', 'test/plugin_functional/config.js', '--esFrom', esFrom, - '--bail', + // '--bail', '--debug', '--kibana-install-dir', KIBANA_INSTALL_DIR, '--', @@ -221,7 +221,7 @@ module.exports = function (grunt) { 'scripts/functional_tests', '--config', 'test/functional/config.js', '--esFrom', esFrom, - '--bail', + // '--bail', '--debug', '--', '--server.maxPayloadBytes=1648576', //default is 1048576 diff --git a/tasks/function_test_groups.js b/tasks/function_test_groups.js index 9ac7bcbf498773..8cbfa19d6ebb5b 100644 --- a/tasks/function_test_groups.js +++ b/tasks/function_test_groups.js @@ -51,7 +51,7 @@ export function getFunctionalTestGroupRunConfigs({ esFrom, kibanaInstallDir } = '--include-tag', tag, '--config', 'test/functional/config.js', '--esFrom', esFrom, - '--bail', + // '--bail', '--debug', '--kibana-install-dir', kibanaInstallDir, '--', diff --git a/test/scripts/jenkins_xpack_ci_group.sh b/test/scripts/jenkins_xpack_ci_group.sh index f6404bb2792f09..99773b8d8b532d 100755 --- a/test/scripts/jenkins_xpack_ci_group.sh +++ b/test/scripts/jenkins_xpack_ci_group.sh @@ -39,6 +39,6 @@ tar -xzf "$linuxBuild" -C "$installDir" --strip=1 export TEST_ES_FROM=${TEST_ES_FROM:-source} echo " -> Running functional and api tests" cd "$XPACK_DIR" -node scripts/functional_tests --debug --bail --kibana-install-dir "$installDir" --include-tag "ciGroup$CI_GROUP" +node scripts/functional_tests --debug --kibana-install-dir "$installDir" --include-tag "ciGroup$CI_GROUP" echo "" echo "" From 9212637ef4b7f8aa43bc5609258674f696c28a01 Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 05:44:24 -0800 Subject: [PATCH 09/21] revert changes to fixture --- .../extract/__tests__/__fixtures__/extract_test_file.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js index a3c24b83263513..33a83f01f53ea7 100644 --- a/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js +++ b/x-pack/plugins/reporting/server/browsers/extract/__tests__/__fixtures__/extract_test_file.js @@ -3,7 +3,6 @@ export const search = { _index: '.kibana', _type: 'search', _id: 'mock-search', - // TODO-VERSION _version: 1, found: true, _source: { @@ -31,7 +30,6 @@ export const visualization = { _index: '.kibana', _type: 'visualization', _id: 'mock-visualization', - // TODO-VERSION _version: 1, found: true, _source: { @@ -55,7 +53,6 @@ export const dashboard = { _index: '.kibana', _type: 'dashboard', _id: 'mock-dashboard', - // TODO-VERSION _version: 1, found: true, _source: { From 20b7579473a2b5c8c6e2ad1ab4a9b6dcd837287a Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 06:04:55 -0800 Subject: [PATCH 10/21] [infra/tests[ update assertions --- .../infra/server/lib/sources/sources.test.ts | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/infra/server/lib/sources/sources.test.ts b/x-pack/plugins/infra/server/lib/sources/sources.test.ts index df0a2324289bc5..2374a83a642dfc 100644 --- a/x-pack/plugins/infra/server/lib/sources/sources.test.ts +++ b/x-pack/plugins/infra/server/lib/sources/sources.test.ts @@ -14,8 +14,7 @@ describe('the InfraSources lib', () => { configuration: createMockStaticConfiguration({}), savedObjects: createMockSavedObjectsService({ id: 'TEST_ID', - // TODO-VERSION - version: 1, + version: 'foo', updated_at: '2000-01-01T00:00:00.000Z', attributes: { metricAlias: 'METRIC_ALIAS', @@ -35,8 +34,7 @@ describe('the InfraSources lib', () => { expect(await sourcesLib.getSourceConfiguration(request, 'TEST_ID')).toMatchObject({ id: 'TEST_ID', - // TODO-VERSION - version: 1, + version: 'foo', updatedAt: 946684800000, configuration: { metricAlias: 'METRIC_ALIAS', @@ -68,8 +66,7 @@ describe('the InfraSources lib', () => { }), savedObjects: createMockSavedObjectsService({ id: 'TEST_ID', - // TODO-VERSION - version: 1, + version: 'foo', updated_at: '2000-01-01T00:00:00.000Z', attributes: { fields: { @@ -83,8 +80,7 @@ describe('the InfraSources lib', () => { expect(await sourcesLib.getSourceConfiguration(request, 'TEST_ID')).toMatchObject({ id: 'TEST_ID', - // TODO-VERSION - version: 1, + version: 'foo', updatedAt: 946684800000, configuration: { metricAlias: 'METRIC_ALIAS', @@ -105,8 +101,7 @@ describe('the InfraSources lib', () => { configuration: createMockStaticConfiguration({}), savedObjects: createMockSavedObjectsService({ id: 'TEST_ID', - // TODO-VERSION - version: 1, + version: 'foo', updated_at: '2000-01-01T00:00:00.000Z', attributes: {}, }), @@ -116,8 +111,7 @@ describe('the InfraSources lib', () => { expect(await sourcesLib.getSourceConfiguration(request, 'TEST_ID')).toMatchObject({ id: 'TEST_ID', - // TODO-VERSION - version: 1, + version: 'foo', updatedAt: 946684800000, configuration: { metricAlias: expect.any(String), From b386f40e42ed27fc1f6d42e476c7e5410f35adf6 Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 07:28:09 -0800 Subject: [PATCH 11/21] [reporting] audit version usage in esqueue --- .../server/lib/__tests__/field_format_map.js | 3 +- .../__tests__/fixtures/elasticsearch.js | 16 +++---- .../server/lib/esqueue/__tests__/job.js | 6 ++- .../server/lib/esqueue/__tests__/worker.js | 42 ++++++++----------- .../reporting/server/lib/esqueue/job.js | 8 ++-- .../reporting/server/lib/esqueue/worker.js | 16 ++++--- 6 files changed, 41 insertions(+), 50 deletions(-) diff --git a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js index 48af5f6856e723..8035776166e9a7 100644 --- a/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js +++ b/x-pack/plugins/reporting/export_types/csv/server/lib/__tests__/field_format_map.js @@ -17,8 +17,7 @@ describe('field format map', function () { const indexPatternSavedObject = { id: 'logstash-*', type: 'index-pattern', - // TODO-VERSION - version: 4, + version: 'abc', attributes: { title: 'logstash-*', timeFieldName: '@timestamp', diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/fixtures/elasticsearch.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/fixtures/elasticsearch.js index a6345e30d6a8c6..70cb912c8f721a 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/fixtures/elasticsearch.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/fixtures/elasticsearch.js @@ -18,8 +18,8 @@ ClientMock.prototype.index = function (params = {}) { _index: params.index || 'index', _type: params.type || constants.DEFAULT_SETTING_DOCTYPE, _id: params.id || uniqueId('testDoc'), - // TODO-VERSION - _version: 1, + _seq_no: 1, + _primary_term: 1, _shards: { total: shardCount, successful: shardCount, failed: 0 }, created: true }); @@ -54,8 +54,8 @@ ClientMock.prototype.get = function (params = {}, source = {}) { _index: params.index || 'index', _type: params.type || constants.DEFAULT_SETTING_DOCTYPE, _id: params.id || 'AVRPRLnlp7Ur1SZXfT-T', - // TODO-VERSION - _version: params.version || 1, + _seq_no: params._seq_no || 1, + _primary_term: params._primary_term || 1, found: true, _source: _source }); @@ -67,8 +67,8 @@ ClientMock.prototype.search = function (params = {}, count = 5, source = {}) { _index: params.index || 'index', _type: params.type || constants.DEFAULT_SETTING_DOCTYPE, _id: uniqueId('documentId'), - // TODO-VERSION - _version: random(1, 5), + _seq_no: random(1, 5), + _primar_term: random(1, 5), _score: null, _source: { created_at: new Date().toString(), @@ -99,8 +99,8 @@ ClientMock.prototype.update = function (params = {}) { _index: params.index || 'index', _type: params.type || constants.DEFAULT_SETTING_DOCTYPE, _id: params.id || uniqueId('testDoc'), - // TODO-VERSION - _version: params.version + 1 || 2, + _seq_no: params.if_seq_no + 1 || 2, + _primary_term: params.if_primary_term + 1 || 2, _shards: { total: shardCount, successful: shardCount, failed: 0 }, created: true }); diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js index 1bdc3589dbb3d6..7aefcf861f6876 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/job.js @@ -135,7 +135,8 @@ describe('Job Class', function () { expect(jobDoc).to.have.property('id'); expect(jobDoc).to.have.property('index'); expect(jobDoc).to.have.property('type'); - expect(jobDoc).to.have.property('version'); + expect(jobDoc).to.have.property('_seq_no'); + expect(jobDoc).to.have.property('_primary_term'); done(); } catch (e) { done(e); @@ -383,7 +384,8 @@ describe('Job Class', function () { expect(doc).to.have.property('index', index); expect(doc).to.have.property('type', jobDoc.type); expect(doc).to.have.property('id', jobDoc.id); - expect(doc).to.have.property('version', jobDoc.version); + expect(doc).to.have.property('_seq_no', jobDoc._seq_no); + expect(doc).to.have.property('_primary_term', jobDoc._primary_term); expect(doc).to.have.property('created_by', defaultCreatedBy); expect(doc).to.have.property('payload'); diff --git a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js index 2aac19b40a0852..76098316b8d121 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/__tests__/worker.js @@ -336,13 +336,6 @@ describe('Worker class', function () { searchStub = sinon.stub(mockQueue.client, 'search').callsFake(() => Promise.resolve({ hits: { hits: [] } })); }); - // TODO-VERSION - it('should query with version', function () { - const params = getSearchParams(); - // TODO-VERSION - expect(params).to.have.property('version', true); - }); - it('should query by default doctype', function () { const params = getSearchParams(); expect(params).to.have.property('type', constants.DEFAULT_SETTING_DOCTYPE); @@ -369,6 +362,11 @@ describe('Worker class', function () { clock.restore(); }); + it('should query with seq_no_primary_term', function () { + const { body } = getSearchParams(jobtype); + expect(body).to.have.property('seq_no_primary_term', true); + }); + it('should filter unwanted source data', function () { const excludedFields = [ 'output.content' ]; const { body } = getSearchParams(jobtype); @@ -434,8 +432,6 @@ describe('Worker class', function () { index: 'myIndex', type: 'test', id: 12345, - // TODO-VERSION - version: 3 }; return mockQueue.client.get(params) .then((jobDoc) => { @@ -449,15 +445,14 @@ describe('Worker class', function () { clock.restore(); }); - // TODO-VERSION - it('should use version on update', function () { + it('should use seqNo and primaryTerm on update', function () { worker._claimJob(job); const query = updateSpy.firstCall.args[0]; expect(query).to.have.property('index', job._index); expect(query).to.have.property('type', job._type); expect(query).to.have.property('id', job._id); - // TODO-VERSION - expect(query).to.have.property('version', job._version); + expect(query).to.have.property('if_seq_no', job._seq_no); + expect(query).to.have.property('if_primary_term', job._primary_term); }); it('should increment the job attempts', function () { @@ -505,8 +500,7 @@ describe('Worker class', function () { expect(msg).to.equal(false); }); - // TODO-VERSION - it('should reject the promise on version errors', function () { + it('should reject the promise on conflict errors', function () { mockQueue.client.update.restore(); sinon.stub(mockQueue.client, 'update').returns(Promise.reject({ statusCode: 409 })); return worker._claimJob(job) @@ -530,8 +524,8 @@ describe('Worker class', function () { _index: 'myIndex', _type: 'test', _id: 12345, - // TODO-VERSION - _version: 3, + _seq_no: 3, + _primary_term: 3, found: true, _source: { jobtype: 'jobtype', @@ -615,15 +609,14 @@ describe('Worker class', function () { clock.restore(); }); - // TODO-VERSION - it('should use version on update', function () { + it('should use _seq_no and _primary_term on update', function () { worker._failJob(job); const query = updateSpy.firstCall.args[0]; expect(query).to.have.property('index', job._index); expect(query).to.have.property('type', job._type); expect(query).to.have.property('id', job._id); - // TODO-VERSION - expect(query).to.have.property('version', job._version); + expect(query).to.have.property('if_seq_no', job._seq_no); + expect(query).to.have.property('if_primary_term', job._primary_term); }); it('should set status to failed', function () { @@ -640,8 +633,7 @@ describe('Worker class', function () { expect(doc.output).to.have.property('content', msg); }); - // TODO-VERSION - it('should return true on version mismatch errors', function () { + it('should return true on conflict errors', function () { mockQueue.client.update.restore(); sinon.stub(mockQueue.client, 'update').returns(Promise.reject({ statusCode: 409 })); return worker._failJob(job) @@ -745,8 +737,8 @@ describe('Worker class', function () { expect(query).to.have.property('index', job._index); expect(query).to.have.property('type', job._type); expect(query).to.have.property('id', job._id); - // TODO-VERSION - expect(query).to.have.property('version', job._version); + expect(query).to.have.property('if_seq_no', job._seq_no); + expect(query).to.have.property('if_primary_term', job._primary_term); expect(query.body.doc).to.have.property('output'); expect(query.body.doc.output).to.have.property('content_type', false); expect(query.body.doc.output).to.have.property('content', payload); diff --git a/x-pack/plugins/reporting/server/lib/esqueue/job.js b/x-pack/plugins/reporting/server/lib/esqueue/job.js index ca83d6ec4990ac..097178a160626b 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/job.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/job.js @@ -82,8 +82,8 @@ export class Job extends events.EventEmitter { id: doc._id, type: doc._type, index: doc._index, - // TODO-VERSION - version: doc._version, + _seq_no: doc._seq_no, + _primary_term: doc._primary_term, }; this.debug(`Job created in index ${this.index}`); @@ -119,8 +119,8 @@ export class Job extends events.EventEmitter { index: doc._index, id: doc._id, type: doc._type, - // TODO-VERSION - version: doc._version, + _seq_no: doc._seq_no, + _primary_term: doc._primary_term, }); }); } diff --git a/x-pack/plugins/reporting/server/lib/esqueue/worker.js b/x-pack/plugins/reporting/server/lib/esqueue/worker.js index 2500d6b5c5d760..383f4cfb47e927 100644 --- a/x-pack/plugins/reporting/server/lib/esqueue/worker.js +++ b/x-pack/plugins/reporting/server/lib/esqueue/worker.js @@ -130,8 +130,8 @@ export class Worker extends events.EventEmitter { index: job._index, type: job._type, id: job._id, - // TODO-VERSION - version: job._version, + if_seq_no: job._seq_no, + if_primary_term: job._primary_term, body: { doc } }) .then((response) => { @@ -168,8 +168,8 @@ export class Worker extends events.EventEmitter { index: job._index, type: job._type, id: job._id, - // TODO-VERSION - version: job._version, + if_seq_no: job._seq_no, + if_primary_term: job._primary_term, body: { doc } }) .then(() => true) @@ -246,8 +246,8 @@ export class Worker extends events.EventEmitter { index: job._index, type: job._type, id: job._id, - // TODO-VERSION - version: job._version, + if_seq_no: job._seq_no, + if_primary_term: job._primary_term, body: { doc } }) .then(() => { @@ -328,7 +328,6 @@ export class Worker extends events.EventEmitter { return claimResult; }) .catch((err) => { - // TODO-VERSION if (err.statusCode === 409) { this.warn(`_claimPendingJobs encountered a version conflict on updating pending job ${job._id}`, err); return; // continue reducing and looking for a different job to claim @@ -355,6 +354,7 @@ export class Worker extends events.EventEmitter { _getPendingJobs() { const nowTime = moment().toISOString(); const query = { + seq_no_primary_term: true, _source: { excludes: [ 'output.content' ] }, @@ -389,8 +389,6 @@ export class Worker extends events.EventEmitter { return this.client.search({ index: `${this.queue.index}-*`, type: this.doctype, - // TODO-VERSION - version: true, body: query }) .then((results) => { From 498301b58add3c647d289dd9ab52690ca7742f62 Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 07:30:14 -0800 Subject: [PATCH 12/21] [courier] audit version usage --- .../saved_object/__tests__/saved_object.js | 17 ++++++----------- .../public/courier/saved_object/saved_object.js | 2 -- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/ui/public/courier/saved_object/__tests__/saved_object.js b/src/ui/public/courier/saved_object/__tests__/saved_object.js index 0b19c8f608be1b..a6a7474f056aab 100644 --- a/src/ui/public/courier/saved_object/__tests__/saved_object.js +++ b/src/ui/public/courier/saved_object/__tests__/saved_object.js @@ -42,14 +42,13 @@ describe('Saved Object', function () { * that can be used to stub es calls. * @param indexPatternId * @param additionalOptions - object that will be assigned to the mocked doc response. - * @returns {{attributes: {}, type: string, id: *, _version: integer}} + * @returns {{attributes: {}, type: string, id: *, _version: string}} */ function getMockedDocResponse(indexPatternId, additionalOptions = {}) { return { type: 'dashboard', id: indexPatternId, - // TODO-VERSION - _version: 2, + _version: 'foo', attributes: {}, ...additionalOptions }; @@ -246,8 +245,7 @@ describe('Saved Object', function () { return BluebirdPromise.resolve({ type: 'dashboard', id: 'myId', - // TODO-VERSION - _version: 2 + _version: 'foo' }); }); @@ -269,8 +267,7 @@ describe('Saved Object', function () { return BluebirdPromise.resolve({ type: 'dashboard', id, - // TODO-VERSION - version: 2 + version: 'foo' }); }); expect(savedObject.isSaving).to.be(false); @@ -309,8 +306,7 @@ describe('Saved Object', function () { sinon.stub(savedObjectsClientStub, 'create').callsFake(() => { return BluebirdPromise.resolve({ id, - // TODO-VERSION - version: 2, + version: 'foo', type: 'dashboard', }); }); @@ -554,8 +550,7 @@ describe('Saved Object', function () { attributes: { title: 'testIndexPattern' }, - // TODO-VERSION - _version: 2 + _version: 'foo' }); const savedObject = new SavedObject(config); diff --git a/src/ui/public/courier/saved_object/saved_object.js b/src/ui/public/courier/saved_object/saved_object.js index 8222b63d37f593..f3c2ffc0e38a7a 100644 --- a/src/ui/public/courier/saved_object/saved_object.js +++ b/src/ui/public/courier/saved_object/saved_object.js @@ -220,13 +220,11 @@ export function SavedObjectProvider(Promise, Private, Notifier, confirmModalProm return savedObjectsClient.get(esType, this.id) .then(resp => { // temporary compatability for savedObjectsClient - return { _id: resp.id, _type: resp.type, _source: _.cloneDeep(resp.attributes), references: resp.references, - // TODO-VERSION found: resp._version ? true : false }; }) From 5645f7bea054c3b31363fd51355b44ffc670fae7 Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 07:32:11 -0800 Subject: [PATCH 13/21] [ui/indexPatterns] audit version usage --- .../__tests__/_index_pattern.test.js | 16 +++++----------- src/ui/public/index_patterns/_index_pattern.js | 7 ------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/ui/public/index_patterns/__tests__/_index_pattern.test.js b/src/ui/public/index_patterns/__tests__/_index_pattern.test.js index 26db4895871815..64f39634770b9f 100644 --- a/src/ui/public/index_patterns/__tests__/_index_pattern.test.js +++ b/src/ui/public/index_patterns/__tests__/_index_pattern.test.js @@ -86,8 +86,7 @@ jest.mock('../unsupported_time_patterns', () => ({ jest.mock('../../saved_objects', () => { const object = { - // TODO-VERSION - _version: 1, + _version: 'foo', _id: 'foo', attributes: { title: 'something' @@ -97,9 +96,7 @@ jest.mock('../../saved_objects', () => { return { SavedObjectsClientProvider: { get: async () => object, - // TODO-VERSION update: async (type, id, body, { version }) => { - // TODO-VERSION if (object._version !== version) { throw { res: { @@ -109,11 +106,11 @@ jest.mock('../../saved_objects', () => { } object.attributes.title = body.title; + object._version += 'a'; return { id: object._id, - // TODO-VERSION - _version: ++object._version, + _version: object._version, }; } }, @@ -134,7 +131,6 @@ const kbnUrl = { const i18n = arg => arg; describe('IndexPattern', () => { - // TODO-VERSION it('should handle version conflicts', async () => { const IndexPattern = IndexPatternProvider(Private, config, Promise, confirmModalPromise, kbnUrl, i18n); // eslint-disable-line new-cap @@ -142,15 +138,13 @@ describe('IndexPattern', () => { const pattern = new IndexPattern('foo'); await pattern.init(); - // TODO-VERSION - expect(pattern.version).toBe(2); + expect(pattern.version).toBe('fooa'); // Create the same one - we're going to handle concurrency const samePattern = new IndexPattern('foo'); await samePattern.init(); - // TODO-VERSION - expect(samePattern.version).toBe(3); + expect(samePattern.version).toBe('fooaa'); // This will conflict because samePattern did a save (from refreshFields) // but the resave should work fine diff --git a/src/ui/public/index_patterns/_index_pattern.js b/src/ui/public/index_patterns/_index_pattern.js index bfe36161a8b4b6..434c5a96f584f7 100644 --- a/src/ui/public/index_patterns/_index_pattern.js +++ b/src/ui/public/index_patterns/_index_pattern.js @@ -179,7 +179,6 @@ export function IndexPatternProvider(Private, config, Promise, confirmModalPromi return id; } - // TODO-VERSION function setVersion(indexPattern, version) { indexPattern.version = version; return version; @@ -247,14 +246,12 @@ export function IndexPatternProvider(Private, config, Promise, confirmModalPromi .then(resp => { // temporary compatability for savedObjectsClient - // TODO-VERSION setVersion(this, resp._version); return { _id: resp.id, _type: resp.type, _source: _.cloneDeep(resp.attributes), - // TODO-VERSION found: resp._version ? true : false }; }) @@ -468,12 +465,9 @@ export function IndexPatternProvider(Private, config, Promise, confirmModalPromi const body = this.prepBody(); // What keys changed since they last pulled the index pattern const originalChangedKeys = Object.keys(body).filter(key => body[key] !== this.originalBody[key]); - // TODO-VERSION return savedObjectsClient.update(type, this.id, body, { version: this.version }) - // TODO-VERSION .then(({ id, _version }) => { setId(this, id); - // TODO-VERSION setVersion(this, _version); }) .catch(err => { @@ -516,7 +510,6 @@ export function IndexPatternProvider(Private, config, Promise, confirmModalPromi this[key] = samePattern[key]; }); - // TODO-VERSION setVersion(this, samePattern.version); // Clear cache From a5550bbe010640d4faecd323d42310ed9e6449cd Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 07:33:38 -0800 Subject: [PATCH 14/21] audit some misc version usage --- .../__tests__/create_or_upgrade_saved_config.js | 5 +---- x-pack/plugins/canvas/server/lib/normalize_type.js | 1 - x-pack/plugins/infra/server/lib/sources/sources.ts | 2 -- .../ml/public/datavisualizer/datavisualizer_controller.js | 1 - .../ml/public/jobs/new_job/advanced/new_job_controller.js | 1 - 5 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js b/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js index bd67cb3e84f88f..8d865f81555efc 100644 --- a/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js +++ b/src/ui/ui_settings/create_or_upgrade_saved_config/__tests__/create_or_upgrade_saved_config.js @@ -41,15 +41,13 @@ describe('uiSettings/createOrUpgradeSavedConfig', function () { create: sinon.stub().callsFake(async (type, attributes, options = {}) => ({ type, id: options.id, - // TODO-VERSION - version: 1, + version: 'foo', })) }; async function run(options = {}) { const resp = await createOrUpgradeSavedConfig({ savedObjectsClient, - // TODO-VERSION version, buildNum, logWithMetadata, @@ -57,7 +55,6 @@ describe('uiSettings/createOrUpgradeSavedConfig', function () { }); sinon.assert.calledOnce(getUpgradeableConfig); - // TODO-VERSION sinon.assert.alwaysCalledWith(getUpgradeableConfig, { savedObjectsClient, version }); return resp; diff --git a/x-pack/plugins/canvas/server/lib/normalize_type.js b/x-pack/plugins/canvas/server/lib/normalize_type.js index 83f71272507dea..b1dd880334308a 100644 --- a/x-pack/plugins/canvas/server/lib/normalize_type.js +++ b/x-pack/plugins/canvas/server/lib/normalize_type.js @@ -17,7 +17,6 @@ export function normalizeType(type) { 'short', 'byte', 'token_count', - // TODO-VERSION '_version', ], date: ['date', 'datetime'], diff --git a/x-pack/plugins/infra/server/lib/sources/sources.ts b/x-pack/plugins/infra/server/lib/sources/sources.ts index 8957e83c5a0357..d4b42a29847a59 100644 --- a/x-pack/plugins/infra/server/lib/sources/sources.ts +++ b/x-pack/plugins/infra/server/lib/sources/sources.ts @@ -44,7 +44,6 @@ export class InfraSources { this.libs.savedObjects.SavedObjectsClient.errors.isNotFoundError(err) ? Promise.resolve({ id: sourceId, - // TODO-VERSION version: undefined, updatedAt: undefined, configuration: staticDefaultSourceConfiguration, @@ -113,7 +112,6 @@ export class InfraSources { ) { const staticDefaultSourceConfiguration = await this.getStaticDefaultSourceConfiguration(); - // TODO-VERSION const { configuration, version } = await this.getSourceConfiguration(request, sourceId); const updatedConfigurationAttributes = updaters.reduce( diff --git a/x-pack/plugins/ml/public/datavisualizer/datavisualizer_controller.js b/x-pack/plugins/ml/public/datavisualizer/datavisualizer_controller.js index b7ebc4b5f6a043..8403d6bf47b04a 100644 --- a/x-pack/plugins/ml/public/datavisualizer/datavisualizer_controller.js +++ b/x-pack/plugins/ml/public/datavisualizer/datavisualizer_controller.js @@ -72,7 +72,6 @@ module // List of system fields we don't want to display. // TODO - are we happy to ignore these fields? - // TODO-VERSION const OMIT_FIELDS = ['_source', '_type', '_index', '_id', '_version', '_score']; $scope.metricCards = []; diff --git a/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js b/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js index 83839046d9ae80..5dea21cf7af866 100644 --- a/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js +++ b/x-pack/plugins/ml/public/jobs/new_job/advanced/new_job_controller.js @@ -106,7 +106,6 @@ module.controller('MlNewJob', '_source', '_type', '_uid', - // TODO-VERSION '_version', '_feature', '_ignored', From 91363deb3b494ff152b57e10cac79abe9230d5f6 Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 19:00:41 -0800 Subject: [PATCH 15/21] [taskManager] update to use seqNo/primaryTerm --- .../task_manager/lib/middleware.test.ts | 11 ++-- x-pack/plugins/task_manager/task.ts | 10 ++- .../plugins/task_manager/task_runner.test.ts | 4 +- .../plugins/task_manager/task_store.test.ts | 61 ++++++++++--------- x-pack/plugins/task_manager/task_store.ts | 42 ++++++------- 5 files changed, 67 insertions(+), 61 deletions(-) diff --git a/x-pack/plugins/task_manager/lib/middleware.test.ts b/x-pack/plugins/task_manager/lib/middleware.test.ts index 5822f9ecdef425..5d81420a319ffe 100644 --- a/x-pack/plugins/task_manager/lib/middleware.test.ts +++ b/x-pack/plugins/task_manager/lib/middleware.test.ts @@ -20,8 +20,8 @@ const getMockTaskInstance = () => ({ const getMockConcreteTaskInstance = () => { const concrete: { id: string; - // TODO-VERSION - version: number; + sequenceNumber: number; + primaryTerm: number; attempts: number; status: TaskStatus; runAt: Date; @@ -30,8 +30,8 @@ const getMockConcreteTaskInstance = () => { params: any; } = { id: 'hy8o99o83', - // TODO-VERSION - version: 1, + sequenceNumber: 1, + primaryTerm: 1, attempts: 0, status: 'idle', runAt: new Date(moment('2018-09-18T05:33:09.588Z').valueOf()), @@ -148,11 +148,12 @@ Object { "params": Object { "abc": "def", }, + "primaryTerm": 1, "runAt": 2018-09-18T05:33:09.588Z, + "sequenceNumber": 1, "state": Object {}, "status": "idle", "taskType": "nice_task", - "version": 1, }, } `); diff --git a/x-pack/plugins/task_manager/task.ts b/x-pack/plugins/task_manager/task.ts index de154761ea6f10..01c2a24e0351d3 100644 --- a/x-pack/plugins/task_manager/task.ts +++ b/x-pack/plugins/task_manager/task.ts @@ -206,10 +206,14 @@ export interface ConcreteTaskInstance extends TaskInstance { id: string; /** - * The version of the Elaticsearch document. + * The sequence number from the Elaticsearch document. */ - // TODO-VERSION - version: number; + sequenceNumber: number; + + /** + * The primary term from the Elaticsearch document. + */ + primaryTerm: number; /** * The number of unsuccessful attempts since the last successful run. This diff --git a/x-pack/plugins/task_manager/task_runner.test.ts b/x-pack/plugins/task_manager/task_runner.test.ts index 4a465c703bdb62..10b65fbcd93d34 100644 --- a/x-pack/plugins/task_manager/task_runner.test.ts +++ b/x-pack/plugins/task_manager/task_runner.test.ts @@ -230,8 +230,8 @@ describe('TaskManagerRunner', () => { { id: 'foo', taskType: 'bar', - // TODO-VERSION - version: 32, + sequenceNumber: 32, + primaryTerm: 32, runAt: new Date(), attempts: 0, params: {}, diff --git a/x-pack/plugins/task_manager/task_store.test.ts b/x-pack/plugins/task_manager/task_store.test.ts index 1708191ce4aaf5..2e908f7b23527b 100644 --- a/x-pack/plugins/task_manager/task_store.test.ts +++ b/x-pack/plugins/task_manager/task_store.test.ts @@ -42,8 +42,8 @@ describe('TaskStore', () => { const callCluster = sinon.spy(() => Promise.resolve({ _id: 'testid', - // TODO-VERSION - _version: 3344, + _seq_no: 3344, + _primary_term: 3344, }) ); const store = new TaskStore({ @@ -90,8 +90,8 @@ describe('TaskStore', () => { expect(result).toMatchObject({ ...task, - // TODO-VERSION - version: 3344, + sequenceNumber: 3344, + primaryTerm: 3344, id: 'testid', }); }); @@ -257,8 +257,8 @@ describe('TaskStore', () => { status: 'idle', taskType: 'foo', user: 'jimbo', - // TODO-VERSION - version: undefined, + sequenceNumber: undefined, + primaryTerm: undefined, }, { attempts: 2, @@ -271,8 +271,8 @@ describe('TaskStore', () => { status: 'running', taskType: 'bar', user: 'dabo', - // TODO-VERSION - version: undefined, + sequenceNumber: undefined, + primaryTerm: undefined, }, ], searchAfter: ['b', 2], @@ -349,8 +349,7 @@ describe('TaskStore', () => { }, size: 10, sort: { 'task.runAt': { order: 'asc' } }, - // TODO-VERSION - version: true, + seq_no_primary_term: true, }, index, }); @@ -410,8 +409,8 @@ describe('TaskStore', () => { status: 'idle', taskType: 'foo', user: 'jimbo', - // TODO-VERSION - version: undefined, + sequenceNumber: undefined, + primaryTerm: undefined, }, { attempts: 2, @@ -424,15 +423,14 @@ describe('TaskStore', () => { status: 'running', taskType: 'bar', user: 'dabo', - // TODO-VERSION - version: undefined, + sequenceNumber: undefined, + primaryTerm: undefined, }, ]); }); }); describe('update', () => { - // TODO-VERSION test('refreshes the index, handles versioning', async () => { const runAt = new Date(); const task = { @@ -441,14 +439,17 @@ describe('TaskStore', () => { params: { hello: 'world' }, state: { foo: 'bar' }, taskType: 'report', - // TODO-VERSION - version: 2, + sequenceNumber: 2, + primaryTerm: 2, attempts: 3, status: 'idle' as TaskStatus, }; - // TODO-VERSION - const callCluster = sinon.spy(async () => ({ _version: task.version + 1 })); + const callCluster = sinon.spy(async () => ({ + _seq_no: task.sequenceNumber + 1, + _primary_term: task.primaryTerm + 1, + })); + const store = new TaskStore({ callCluster, index: 'tasky', @@ -464,14 +465,13 @@ describe('TaskStore', () => { expect(callCluster.args[0][1]).toMatchObject({ id: task.id, index: 'tasky', - // TODO-VERSION - version: 2, + if_seq_no: 2, + if_primary_term: 2, refresh: true, body: { doc: { task: { - // TODO-VERSION - ...['id', 'version'].reduce((acc, prop) => _.omit(acc, prop), task), + ..._.omit(task, ['id', 'sequenceNumber', 'primaryTerm']), params: JSON.stringify(task.params), state: JSON.stringify(task.state), }, @@ -479,8 +479,11 @@ describe('TaskStore', () => { }, }); - // TODO-VERSION - expect(result).toEqual({ ...task, version: 3 }); + expect(result).toEqual({ + ...task, + sequenceNumber: 3, + primaryTerm: 3, + }); }); }); @@ -491,8 +494,8 @@ describe('TaskStore', () => { Promise.resolve({ _index: 'myindex', _id: id, - // TODO-VERSION - _version: 32, + _seq_no: 32, + _primary_term: 32, result: 'deleted', }) ); @@ -510,8 +513,8 @@ describe('TaskStore', () => { expect(result).toEqual({ id, index: 'myindex', - // TODO-VERSION - version: 32, + sequenceNumber: 32, + primaryTerm: 32, result: 'deleted', }); diff --git a/x-pack/plugins/task_manager/task_store.ts b/x-pack/plugins/task_manager/task_store.ts index be77749c44653c..fd2b9c1c720aa6 100644 --- a/x-pack/plugins/task_manager/task_store.ts +++ b/x-pack/plugins/task_manager/task_store.ts @@ -33,8 +33,8 @@ export interface FetchResult { export interface RemoveResult { index: string; id: string; - // TODO-VERSION - version: string; + sequenceNumber: number; + primaryTerm: number; result: string; } @@ -42,8 +42,8 @@ export interface RemoveResult { export interface RawTaskDoc { _id: string; _index: string; - // TODO-VERSION - _version: number; + _seq_no: number; + _primary_term: number; _source: { type: string; task: { @@ -181,8 +181,8 @@ export class TaskStore { return { ...taskInstance, id: result._id, - // TODO-VERSION - version: result._version, + sequenceNumber: result._seq_no, + primaryTerm: result._primary_term, attempts: 0, status: task.status, runAt: task.runAt, @@ -228,8 +228,7 @@ export class TaskStore { }, size: 10, sort: { 'task.runAt': { order: 'asc' } }, - // TODO-VERSION - version: true, + seq_no_primary_term: true, }); return docs; @@ -245,15 +244,14 @@ export class TaskStore { public async update(doc: ConcreteTaskInstance): Promise { const rawDoc = taskDocToRaw(doc, this.index); - // TODO-VERSION - const { _version } = await this.callCluster('update', { + const result = await this.callCluster('update', { body: { doc: rawDoc._source, }, id: doc.id, index: this.index, - // TODO-VERSION - version: doc.version, + if_seq_no: doc.sequenceNumber, + if_primary_term: doc.primaryTerm, // The refresh is important so that if we immediately look for work, // we don't pick up this task. refresh: true, @@ -261,8 +259,8 @@ export class TaskStore { return { ...doc, - // TODO-VERSION - version: _version, + sequenceNumber: result._seq_no, + primaryTerm: result._primary_term, }; } @@ -284,8 +282,8 @@ export class TaskStore { return { index: result._index, id: result._id, - // TODO-VERSION - version: result._version, + sequenceNumber: result._seq_no, + primaryTerm: result._primary_term, result: result.result, }; } @@ -341,8 +339,8 @@ function rawSource(doc: TaskInstance) { }; delete (source as any).id; - // TODO-VERSION - delete (source as any).version; + delete (source as any).sequenceNumber; + delete (source as any).primaryTerm; delete (source as any).type; return { @@ -359,8 +357,8 @@ function taskDocToRaw(doc: ConcreteTaskInstance, index: string): RawTaskDoc { _id: doc.id, _index: index, _source: { type, task }, - // TODO-VERSION - _version: doc.version, + _seq_no: doc.sequenceNumber, + _primary_term: doc.primaryTerm, }; } @@ -368,8 +366,8 @@ function rawToTaskDoc(doc: RawTaskDoc): ConcreteTaskInstance { return { ...doc._source.task, id: doc._id, - // TODO-VERSION - version: doc._version, + sequenceNumber: doc._seq_no, + primaryTerm: doc._primary_term, params: parseJSONField(doc._source.task.params, 'params', doc), state: parseJSONField(doc._source.task.state, 'state', doc), }; From 077245fed8eb83f03cb01efe58440e9ed6e45ee2 Mon Sep 17 00:00:00 2001 From: spalger Date: Sat, 2 Feb 2019 19:07:41 -0800 Subject: [PATCH 16/21] [ml] job_version is a semver version for the ML api https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-job.html --- x-pack/plugins/ml/common/types/jobs.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/ml/common/types/jobs.ts b/x-pack/plugins/ml/common/types/jobs.ts index dfbffb7fb88069..5484a288308212 100644 --- a/x-pack/plugins/ml/common/types/jobs.ts +++ b/x-pack/plugins/ml/common/types/jobs.ts @@ -29,7 +29,6 @@ export interface MlJob { finished_time: number; job_id: string; job_type: string; - // TODO-VERSION job_version: string; model_plot_config: object; model_size_stats: object; From 52d890fed7126eb2a154b0b9e9de13bd619d9c60 Mon Sep 17 00:00:00 2001 From: spalger Date: Sun, 3 Feb 2019 08:49:04 -0800 Subject: [PATCH 17/21] [beatscm] update to use seqNo/primaryTerm, remove unused method --- .../lib/adapters/database/adapter_types.ts | 50 ++++++++----------- .../database/kibana_database_adapter.ts | 39 --------------- 2 files changed, 22 insertions(+), 67 deletions(-) diff --git a/x-pack/plugins/beats_management/server/lib/adapters/database/adapter_types.ts b/x-pack/plugins/beats_management/server/lib/adapters/database/adapter_types.ts index 40642fb56359f1..c56bc6d72c7a7f 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/database/adapter_types.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/database/adapter_types.ts @@ -100,8 +100,8 @@ export interface DatabaseSearchResponse { _id: string; _score: number; _source: T; - // TODO-VERSION - _version?: number; + _seq_no?: number; + _primary_term?: number; _explanation?: DatabaseExplanation; fields?: any; highlight?: any; @@ -129,8 +129,8 @@ export interface DatabaseGetDocumentResponse { _index: string; _type: string; _id: string; - // TODO-VERSION - _version: number; + _seq_no: number; + _primary_term: number; found: boolean; _source: Source; } @@ -184,9 +184,8 @@ export interface DatabaseDeleteDocumentParams extends DatabaseGenericParams { refresh?: DatabaseRefresh; routing?: string; timeout?: string; - // TODO-VERSION - version?: number; - versionType?: DatabaseVersionType; + ifSeqNo?: number; + ifPrimaryTerm?: number; index: string; type: string; id: string; @@ -197,8 +196,8 @@ export interface DatabaseIndexDocumentResponse { _index: string; _type: string; _id: string; - // TODO-VERSION - _version: number; + _seq_no: number; + _primary_term: number; result: string; } @@ -207,8 +206,8 @@ export interface DatabaseUpdateDocumentResponse { _index: string; _type: string; _id: string; - // TODO-VERSION - _version: number; + _seq_no: number; + _primary_term: number; result: string; } @@ -217,8 +216,8 @@ export interface DatabaseDeleteDocumentResponse { _index: string; _type: string; _id: string; - // TODO-VERSION - _version: number; + _seq_no: number; + _primary_term: number; result: string; } @@ -231,9 +230,8 @@ export interface DatabaseIndexDocumentParams extends DatabaseGenericParams { timeout?: string; timestamp?: Date | number; ttl?: string; - // TODO-VERSION - version?: number; - versionType?: DatabaseVersionType; + ifSeqNo?: number; + ifPrimaryTerm?: number; pipeline?: string; id?: string; index: string; @@ -253,9 +251,8 @@ export interface DatabaseCreateDocumentParams extends DatabaseGenericParams { timeout?: string; timestamp?: Date | number; ttl?: string; - // TODO-VERSION - version?: number; - versionType?: DatabaseVersionType; + ifSeqNo?: number; + ifPrimaryTerm?: number; pipeline?: string; id?: string; index: string; @@ -273,9 +270,8 @@ export interface DatabaseDeleteDocumentParams extends DatabaseGenericParams { refresh?: DatabaseRefresh; routing?: string; timeout?: string; - // TODO-VERSION - version?: number; - versionType?: DatabaseVersionType; + ifSeqNo?: number; + ifPrimaryTerm?: number; index: string; type: string; id: string; @@ -291,9 +287,8 @@ export interface DatabaseGetParams extends DatabaseGenericParams { _source?: DatabaseNameList; _sourceExclude?: DatabaseNameList; _source_includes?: DatabaseNameList; - // TODO-VERSION - version?: number; - versionType?: DatabaseVersionType; + ifSeqNo?: number; + ifPrimaryTerm?: number; id: string; index: string; type: string; @@ -301,7 +296,6 @@ export interface DatabaseGetParams extends DatabaseGenericParams { export type DatabaseNameList = string | string[] | boolean; export type DatabaseRefresh = boolean | 'true' | 'false' | 'wait_for' | ''; -export type DatabaseVersionType = 'internal' | 'external' | 'external_gte' | 'force'; export type ExpandWildcards = 'open' | 'closed' | 'none' | 'all'; export type DefaultOperator = 'AND' | 'OR'; export type DatabaseConflicts = 'abort' | 'proceed'; @@ -320,7 +314,7 @@ export interface DatabaseDeleteDocumentResponse { _index: string; _type: string; _id: string; - // TODO-VERSION - _version: number; + _seq_no: number; + _primary_term: number; result: string; } diff --git a/x-pack/plugins/beats_management/server/lib/adapters/database/kibana_database_adapter.ts b/x-pack/plugins/beats_management/server/lib/adapters/database/kibana_database_adapter.ts index 2aab29417559c0..8bec4307d46eb5 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/database/kibana_database_adapter.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/database/kibana_database_adapter.ts @@ -3,7 +3,6 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { get } from 'lodash'; import { INDEX_NAMES } from 'x-pack/plugins/beats_management/common/constants'; import { beatsIndexTemplate } from '../../../utils/index_templates'; import { FrameworkUser } from '../framework/adapter_types'; @@ -120,44 +119,6 @@ export class KibanaDatabaseAdapter implements DatabaseAdapter { return result; } - private async fetchAllFromScroll( - user: FrameworkUser, - response: DatabaseSearchResponse, - hits: DatabaseSearchResponse['hits']['hits'] = [] - ): Promise< - Array<{ - _index: string; - _type: string; - _id: string; - _score: number; - _source: Source; - // TODO-VERSION - _version?: number; - fields?: any; - highlight?: any; - inner_hits?: any; - sort?: string[]; - }> - > { - const newHits = get(response, 'hits.hits', []); - const scrollId = get(response, '_scroll_id'); - - if (newHits.length > 0) { - hits.push(...newHits); - - return this.callWithUser(user, 'scroll', { - body: { - scroll: '30s', - scroll_id: scrollId, - }, - }).then((innerResponse: DatabaseSearchResponse) => { - return this.fetchAllFromScroll(user, innerResponse, hits); - }); - } - - return Promise.resolve(hits); - } - private callWithUser(user: FrameworkUser, esMethod: string, options: any = {}): any { if (user.kind === 'authenticated') { return this.es.callWithRequest( From 57190351e132944fa2e7d0b83463d5732ad950d3 Mon Sep 17 00:00:00 2001 From: spalger Date: Sun, 3 Feb 2019 18:12:21 -0800 Subject: [PATCH 18/21] [beatscm] these versions refer to release versions --- x-pack/plugins/beats_management/common/domain_types.ts | 2 -- x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts | 1 - 2 files changed, 3 deletions(-) diff --git a/x-pack/plugins/beats_management/common/domain_types.ts b/x-pack/plugins/beats_management/common/domain_types.ts index 4d74d1a5976968..858e25ff5f562f 100644 --- a/x-pack/plugins/beats_management/common/domain_types.ts +++ b/x-pack/plugins/beats_management/common/domain_types.ts @@ -45,7 +45,6 @@ export interface CMBeat { access_token: string; verified_on?: string; type: string; - // TODO-VERSION version?: string; host_ip: string; host_name: string; @@ -63,7 +62,6 @@ export interface CMBeat { export interface ConfigBlockSchema { id: string; name: string; - // TODO-VERSION version: number; allowOtherConfigs?: boolean; configs: BeatConfigSchema[]; diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts b/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts index 7b1691200d89c2..9f3feb4651bd29 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts @@ -27,7 +27,6 @@ export const createBeatEnrollmentRoute = (libs: CMServerLibs) => ({ host_name: Joi.string().required(), name: Joi.string().required(), type: Joi.string().required(), - // TODO-VERSION version: Joi.string().required(), }).required(), }, From 3b958113a3f4c772f33719e8fa7271ffbd8a0502 Mon Sep 17 00:00:00 2001 From: spalger Date: Sun, 3 Feb 2019 18:12:43 -0800 Subject: [PATCH 19/21] Revert "disable --bail" This reverts commit 35343fc1493694bf91a2b858bf34d829d0eef43c. --- tasks/config/run.js | 8 ++++---- tasks/function_test_groups.js | 2 +- test/scripts/jenkins_xpack_ci_group.sh | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tasks/config/run.js b/tasks/config/run.js index 1985392d8f9c2e..4d2c1a11d34529 100644 --- a/tasks/config/run.js +++ b/tasks/config/run.js @@ -183,7 +183,7 @@ module.exports = function (grunt) { 'scripts/functional_tests', '--config', 'test/api_integration/config.js', '--esFrom', esFrom, - // '--bail', + '--bail', '--debug', ], }, @@ -195,7 +195,7 @@ module.exports = function (grunt) { '--config', 'test/server_integration/http/ssl/config.js', '--config', 'test/server_integration/http/ssl_redirect/config.js', '--esFrom', esFrom, - // '--bail', + '--bail', '--debug', '--kibana-install-dir', KIBANA_INSTALL_DIR, ], @@ -207,7 +207,7 @@ module.exports = function (grunt) { 'scripts/functional_tests', '--config', 'test/plugin_functional/config.js', '--esFrom', esFrom, - // '--bail', + '--bail', '--debug', '--kibana-install-dir', KIBANA_INSTALL_DIR, '--', @@ -221,7 +221,7 @@ module.exports = function (grunt) { 'scripts/functional_tests', '--config', 'test/functional/config.js', '--esFrom', esFrom, - // '--bail', + '--bail', '--debug', '--', '--server.maxPayloadBytes=1648576', //default is 1048576 diff --git a/tasks/function_test_groups.js b/tasks/function_test_groups.js index 8cbfa19d6ebb5b..9ac7bcbf498773 100644 --- a/tasks/function_test_groups.js +++ b/tasks/function_test_groups.js @@ -51,7 +51,7 @@ export function getFunctionalTestGroupRunConfigs({ esFrom, kibanaInstallDir } = '--include-tag', tag, '--config', 'test/functional/config.js', '--esFrom', esFrom, - // '--bail', + '--bail', '--debug', '--kibana-install-dir', kibanaInstallDir, '--', diff --git a/test/scripts/jenkins_xpack_ci_group.sh b/test/scripts/jenkins_xpack_ci_group.sh index 99773b8d8b532d..f6404bb2792f09 100755 --- a/test/scripts/jenkins_xpack_ci_group.sh +++ b/test/scripts/jenkins_xpack_ci_group.sh @@ -39,6 +39,6 @@ tar -xzf "$linuxBuild" -C "$installDir" --strip=1 export TEST_ES_FROM=${TEST_ES_FROM:-source} echo " -> Running functional and api tests" cd "$XPACK_DIR" -node scripts/functional_tests --debug --kibana-install-dir "$installDir" --include-tag "ciGroup$CI_GROUP" +node scripts/functional_tests --debug --bail --kibana-install-dir "$installDir" --include-tag "ciGroup$CI_GROUP" echo "" echo "" From 935f7ccdcafa5fc0ff57eb7b6a04f3c899ebf9c2 Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 4 Feb 2019 18:01:43 -0600 Subject: [PATCH 20/21] [savedObjects/version] break up version mode and thoroughly test it --- .../saved_objects/serialization/index.ts | 2 +- .../serialization/serialization.test.ts | 2 +- .../service/lib/repository.test.js | 2 +- src/server/saved_objects/version/base64.ts | 21 ++++ .../version/decode_request_version.test.ts | 35 ++++++ .../version/decode_request_version.ts | 32 ++++++ .../version/decode_version.test.ts | 102 ++++++++++++++++++ .../version.ts => version/decode_version.ts} | 45 +------- .../version/encode_hit_version.test.ts | 30 ++++++ .../version/encode_hit_version.ts | 28 +++++ .../version/encode_version.test.ts | 62 +++++++++++ .../saved_objects/version/encode_version.ts | 37 +++++++ src/server/saved_objects/version/index.ts | 23 ++++ 13 files changed, 376 insertions(+), 45 deletions(-) create mode 100644 src/server/saved_objects/version/base64.ts create mode 100644 src/server/saved_objects/version/decode_request_version.test.ts create mode 100644 src/server/saved_objects/version/decode_request_version.ts create mode 100644 src/server/saved_objects/version/decode_version.test.ts rename src/server/saved_objects/{service/lib/version.ts => version/decode_version.ts} (52%) create mode 100644 src/server/saved_objects/version/encode_hit_version.test.ts create mode 100644 src/server/saved_objects/version/encode_hit_version.ts create mode 100644 src/server/saved_objects/version/encode_version.test.ts create mode 100644 src/server/saved_objects/version/encode_version.ts create mode 100644 src/server/saved_objects/version/index.ts diff --git a/src/server/saved_objects/serialization/index.ts b/src/server/saved_objects/serialization/index.ts index 74bfe9443bd5ee..00a9e81e5c1c36 100644 --- a/src/server/saved_objects/serialization/index.ts +++ b/src/server/saved_objects/serialization/index.ts @@ -24,7 +24,7 @@ import uuid from 'uuid'; import { SavedObjectsSchema } from '../schema'; -import { decodeVersion, encodeVersion } from '../service/lib/version'; +import { decodeVersion, encodeVersion } from '../version'; /** * A raw document as represented directly in the saved object index. diff --git a/src/server/saved_objects/serialization/serialization.test.ts b/src/server/saved_objects/serialization/serialization.test.ts index ce2090e88d11fc..e8bcdde73fcf4b 100644 --- a/src/server/saved_objects/serialization/serialization.test.ts +++ b/src/server/saved_objects/serialization/serialization.test.ts @@ -20,7 +20,7 @@ import _ from 'lodash'; import { SavedObjectsSerializer } from '.'; import { SavedObjectsSchema } from '../schema'; -import { encodeVersion } from '../service/lib/version'; +import { encodeVersion } from '../version'; describe('saved object conversion', () => { describe('#rawToSavedObject', () => { diff --git a/src/server/saved_objects/service/lib/repository.test.js b/src/server/saved_objects/service/lib/repository.test.js index e93146e98d788f..c76d2fd50c1424 100644 --- a/src/server/saved_objects/service/lib/repository.test.js +++ b/src/server/saved_objects/service/lib/repository.test.js @@ -26,7 +26,7 @@ import * as errors from './errors'; import elasticsearch from 'elasticsearch'; import { SavedObjectsSchema } from '../../schema'; import { SavedObjectsSerializer } from '../../serialization'; -import { encodeHitVersion } from './version'; +import { encodeHitVersion } from '../../version'; // BEWARE: The SavedObjectClient depends on the implementation details of the SavedObjectsRepository // so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient. diff --git a/src/server/saved_objects/version/base64.ts b/src/server/saved_objects/version/base64.ts new file mode 100644 index 00000000000000..b82b496a2fbb54 --- /dev/null +++ b/src/server/saved_objects/version/base64.ts @@ -0,0 +1,21 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export const decodeBase64 = (base64: string) => Buffer.from(base64, 'base64').toString('utf8'); +export const encodeBase64 = (utf8: string) => Buffer.from(utf8, 'utf8').toString('base64'); diff --git a/src/server/saved_objects/version/decode_request_version.test.ts b/src/server/saved_objects/version/decode_request_version.test.ts new file mode 100644 index 00000000000000..e2e9665be35cd7 --- /dev/null +++ b/src/server/saved_objects/version/decode_request_version.test.ts @@ -0,0 +1,35 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +jest.mock('./decode_version', () => ({ + decodeVersion: jest.fn().mockReturnValue({ _seq_no: 1, _primary_term: 2 }), +})); + +import { decodeRequestVersion } from './decode_request_version'; +import { decodeVersion } from './decode_version'; + +it('renames decodeVersion() return value to use if_seq_no and if_primary_term', () => { + expect(decodeRequestVersion('foobar')).toMatchInlineSnapshot(` +Object { + "if_primary_term": 2, + "if_seq_no": 1, +} +`); + expect(decodeVersion).toHaveBeenCalledWith('foobar'); +}); diff --git a/src/server/saved_objects/version/decode_request_version.ts b/src/server/saved_objects/version/decode_request_version.ts new file mode 100644 index 00000000000000..dc01262a664095 --- /dev/null +++ b/src/server/saved_objects/version/decode_request_version.ts @@ -0,0 +1,32 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { decodeVersion } from './decode_version'; + +/** + * Helper for decoding version to request params that are driven + * by the version info + */ +export function decodeRequestVersion(version?: string) { + const decoded = decodeVersion(version); + return { + if_seq_no: decoded._seq_no, + if_primary_term: decoded._primary_term, + }; +} diff --git a/src/server/saved_objects/version/decode_version.test.ts b/src/server/saved_objects/version/decode_version.test.ts new file mode 100644 index 00000000000000..b157d97ae8a239 --- /dev/null +++ b/src/server/saved_objects/version/decode_version.test.ts @@ -0,0 +1,102 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import Boom from 'boom'; + +import { decodeVersion } from './decode_version'; + +describe('decodeVersion', () => { + it('parses version back into {_seq_no,_primary_term} object', () => { + expect(decodeVersion('WzQsMV0=')).toMatchInlineSnapshot(` +Object { + "_primary_term": 1, + "_seq_no": 4, +} +`); + }); + + it('throws Boom error if not in base64', () => { + let error; + try { + decodeVersion('[1,4]'); + } catch (err) { + error = err; + } + + expect(error.message).toMatchInlineSnapshot(`"Invalid version [[1,4]]"`); + expect(Boom.isBoom(error)).toBe(true); + expect(error.output).toMatchInlineSnapshot(` +Object { + "headers": Object {}, + "payload": Object { + "error": "Bad Request", + "message": "Invalid version [[1,4]]", + "statusCode": 400, + }, + "statusCode": 400, +} +`); + }); + + it('throws if not JSON encoded', () => { + let error; + try { + decodeVersion('MSwy'); + } catch (err) { + error = err; + } + + expect(error.message).toMatchInlineSnapshot(`"Invalid version [MSwy]"`); + expect(Boom.isBoom(error)).toBe(true); + expect(error.output).toMatchInlineSnapshot(` +Object { + "headers": Object {}, + "payload": Object { + "error": "Bad Request", + "message": "Invalid version [MSwy]", + "statusCode": 400, + }, + "statusCode": 400, +} +`); + }); + + it('throws if either value is not an integer', () => { + let error; + try { + decodeVersion('WzEsMy41XQ=='); + } catch (err) { + error = err; + } + + expect(error.message).toMatchInlineSnapshot(`"Invalid version [WzEsMy41XQ==]"`); + expect(Boom.isBoom(error)).toBe(true); + expect(error.output).toMatchInlineSnapshot(` +Object { + "headers": Object {}, + "payload": Object { + "error": "Bad Request", + "message": "Invalid version [WzEsMy41XQ==]", + "statusCode": 400, + }, + "statusCode": 400, +} +`); + }); +}); diff --git a/src/server/saved_objects/service/lib/version.ts b/src/server/saved_objects/version/decode_version.ts similarity index 52% rename from src/server/saved_objects/service/lib/version.ts rename to src/server/saved_objects/version/decode_version.ts index 5d04d914ffcefd..92e06c080b087d 100644 --- a/src/server/saved_objects/service/lib/version.ts +++ b/src/server/saved_objects/version/decode_version.ts @@ -17,35 +17,8 @@ * under the License. */ -import { createInvalidVersionError } from './errors'; - -const decodeBase64 = (base64: string) => Buffer.from(base64, 'base64').toString('utf8'); -const encodeBase64 = (utf8: string) => Buffer.from(utf8, 'utf8').toString('base64'); - -/** - * Encode the sequence params into an "opaque" version string - * that can be used in the saved object API in place of numeric - * version numbers - */ -export function encodeVersion(seqNo: number, primaryTerm: number) { - if (!Number.isInteger(primaryTerm)) { - throw new TypeError('_primary_term from elasticsearch must be an integer'); - } - - if (!Number.isInteger(seqNo)) { - throw new TypeError('_seq_no from elasticsearch must be an integer'); - } - - return encodeBase64(JSON.stringify([seqNo, primaryTerm])); -} - -/** - * Helper for encoding a version from a "hit" (hits.hits[#] from _search) or - * "doc" (body from GET, update, etc) object - */ -export function encodeHitVersion(response: { _seq_no: number; _primary_term: number }) { - return encodeVersion(response._seq_no, response._primary_term); -} +import { createInvalidVersionError } from '../service/lib/errors'; +import { decodeBase64 } from './base64'; /** * Decode the "opaque" version string to the sequence params we @@ -60,7 +33,7 @@ export function decodeVersion(version?: string) { const seqParams = JSON.parse(decodeBase64(version)) as [number, number]; if ( - !seqParams || + !Array.isArray(seqParams) || seqParams.length !== 2 || !Number.isInteger(seqParams[0]) || !Number.isInteger(seqParams[1]) @@ -76,15 +49,3 @@ export function decodeVersion(version?: string) { throw createInvalidVersionError(version); } } - -/** - * Helper for decoding version to request params that are driven - * by the version info - */ -export function decodeRequestVersion(version?: string) { - const decoded = decodeVersion(version); - return { - if_seq_no: decoded._seq_no, - if_primary_term: decoded._primary_term, - }; -} diff --git a/src/server/saved_objects/version/encode_hit_version.test.ts b/src/server/saved_objects/version/encode_hit_version.test.ts new file mode 100644 index 00000000000000..29c0ab59740cda --- /dev/null +++ b/src/server/saved_objects/version/encode_hit_version.test.ts @@ -0,0 +1,30 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +jest.mock('./encode_version', () => ({ + encodeVersion: jest.fn().mockReturnValue('foo'), +})); + +import { encodeHitVersion } from './encode_hit_version'; +import { encodeVersion } from './encode_version'; + +it('renames decodeVersion() return value to use if_seq_no and if_primary_term', () => { + expect(encodeHitVersion({ _seq_no: 1, _primary_term: 2 })).toMatchInlineSnapshot(`"foo"`); + expect(encodeVersion).toHaveBeenCalledWith(1, 2); +}); diff --git a/src/server/saved_objects/version/encode_hit_version.ts b/src/server/saved_objects/version/encode_hit_version.ts new file mode 100644 index 00000000000000..bb0bd5e5c0d3ce --- /dev/null +++ b/src/server/saved_objects/version/encode_hit_version.ts @@ -0,0 +1,28 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { encodeVersion } from './encode_version'; + +/** + * Helper for encoding a version from a "hit" (hits.hits[#] from _search) or + * "doc" (body from GET, update, etc) object + */ +export function encodeHitVersion(response: { _seq_no: number; _primary_term: number }) { + return encodeVersion(response._seq_no, response._primary_term); +} diff --git a/src/server/saved_objects/version/encode_version.test.ts b/src/server/saved_objects/version/encode_version.test.ts new file mode 100644 index 00000000000000..9f9d9140f939b1 --- /dev/null +++ b/src/server/saved_objects/version/encode_version.test.ts @@ -0,0 +1,62 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { encodeVersion } from './encode_version'; + +describe('encodeVersion', () => { + it('throws if primaryTerm is not an integer', () => { + expect(() => encodeVersion(1, undefined as any)).toThrowErrorMatchingInlineSnapshot( + `"_primary_term from elasticsearch must be an integer"` + ); + expect(() => encodeVersion(1, null as any)).toThrowErrorMatchingInlineSnapshot( + `"_primary_term from elasticsearch must be an integer"` + ); + expect(() => encodeVersion(1, {} as any)).toThrowErrorMatchingInlineSnapshot( + `"_primary_term from elasticsearch must be an integer"` + ); + expect(() => encodeVersion(1, [] as any)).toThrowErrorMatchingInlineSnapshot( + `"_primary_term from elasticsearch must be an integer"` + ); + expect(() => encodeVersion(1, 2.5 as any)).toThrowErrorMatchingInlineSnapshot( + `"_primary_term from elasticsearch must be an integer"` + ); + }); + + it('throws if seqNo is not an integer', () => { + expect(() => encodeVersion(undefined as any, 1)).toThrowErrorMatchingInlineSnapshot( + `"_seq_no from elasticsearch must be an integer"` + ); + expect(() => encodeVersion(null as any, 1)).toThrowErrorMatchingInlineSnapshot( + `"_seq_no from elasticsearch must be an integer"` + ); + expect(() => encodeVersion({} as any, 1)).toThrowErrorMatchingInlineSnapshot( + `"_seq_no from elasticsearch must be an integer"` + ); + expect(() => encodeVersion([] as any, 1)).toThrowErrorMatchingInlineSnapshot( + `"_seq_no from elasticsearch must be an integer"` + ); + expect(() => encodeVersion(2.5 as any, 1)).toThrowErrorMatchingInlineSnapshot( + `"_seq_no from elasticsearch must be an integer"` + ); + }); + + it('returns a base64 encoded, JSON string of seqNo and primaryTerm', () => { + expect(encodeVersion(123, 456)).toMatchInlineSnapshot(`"WzEyMyw0NTZd"`); + }); +}); diff --git a/src/server/saved_objects/version/encode_version.ts b/src/server/saved_objects/version/encode_version.ts new file mode 100644 index 00000000000000..9b0fcdfbab50c5 --- /dev/null +++ b/src/server/saved_objects/version/encode_version.ts @@ -0,0 +1,37 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { encodeBase64 } from './base64'; + +/** + * Encode the sequence params into an "opaque" version string + * that can be used in the saved object API in place of numeric + * version numbers + */ +export function encodeVersion(seqNo: number, primaryTerm: number) { + if (!Number.isInteger(primaryTerm)) { + throw new TypeError('_primary_term from elasticsearch must be an integer'); + } + + if (!Number.isInteger(seqNo)) { + throw new TypeError('_seq_no from elasticsearch must be an integer'); + } + + return encodeBase64(JSON.stringify([seqNo, primaryTerm])); +} diff --git a/src/server/saved_objects/version/index.ts b/src/server/saved_objects/version/index.ts new file mode 100644 index 00000000000000..73dce67462978f --- /dev/null +++ b/src/server/saved_objects/version/index.ts @@ -0,0 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export * from './encode_version'; +export * from './encode_hit_version'; +export * from './decode_version'; +export * from './decode_request_version'; From 687e1ec25993e73fed5e288df9d97fa6beda3838 Mon Sep 17 00:00:00 2001 From: spalger Date: Mon, 4 Feb 2019 18:36:12 -0600 Subject: [PATCH 21/21] fix broken import --- src/server/saved_objects/service/lib/repository.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/saved_objects/service/lib/repository.js b/src/server/saved_objects/service/lib/repository.js index 70723ba36a52bd..009163972fad15 100644 --- a/src/server/saved_objects/service/lib/repository.js +++ b/src/server/saved_objects/service/lib/repository.js @@ -23,7 +23,7 @@ import { getSearchDsl } from './search_dsl'; import { includedFields } from './included_fields'; import { decorateEsError } from './decorate_es_error'; import * as errors from './errors'; -import { decodeRequestVersion, encodeVersion, encodeHitVersion } from './version'; +import { decodeRequestVersion, encodeVersion, encodeHitVersion } from '../../version'; // BEWARE: The SavedObjectClient depends on the implementation details of the SavedObjectsRepository // so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient.