diff --git a/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/app/services/api.js b/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/app/services/api.js index b50c36aa8df9f..24bc7e17356e2 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/app/services/api.js +++ b/x-pack/legacy/plugins/cross_cluster_replication/public/np_ready/app/services/api.js @@ -145,9 +145,35 @@ export const updateFollowerIndex = (id, followerIndex) => { if (isUsingAdvancedSettings) { uiMetrics.push(UIM_FOLLOWER_INDEX_USE_ADVANCED_OPTIONS); } + + const { + maxReadRequestOperationCount, + maxOutstandingReadRequests, + maxReadRequestSize, + maxWriteRequestOperationCount, + maxWriteRequestSize, + maxOutstandingWriteRequests, + maxWriteBufferCount, + maxWriteBufferSize, + maxRetryDelay, + readPollTimeout, + } = followerIndex; + const request = httpClient.put(`${API_BASE_PATH}/follower_indices/${encodeURIComponent(id)}`, { - body: JSON.stringify(followerIndex), + body: JSON.stringify({ + maxReadRequestOperationCount, + maxOutstandingReadRequests, + maxReadRequestSize, + maxWriteRequestOperationCount, + maxWriteRequestSize, + maxOutstandingWriteRequests, + maxWriteBufferCount, + maxWriteBufferSize, + maxRetryDelay, + readPollTimeout, + }), }); + return trackUserRequest(request, uiMetrics); }; diff --git a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts index 3896e1c02c915..1d7dacf4a8688 100644 --- a/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts +++ b/x-pack/legacy/plugins/cross_cluster_replication/server/np_ready/routes/api/follower_index.ts @@ -164,6 +164,18 @@ export const registerFollowerIndexRoutes = ({ router, __LEGACY }: RouteDependenc path: `${API_BASE_PATH}/follower_indices/{id}`, validate: { params: schema.object({ id: schema.string() }), + body: schema.object({ + maxReadRequestOperationCount: schema.maybe(schema.number()), + maxOutstandingReadRequests: schema.maybe(schema.number()), + maxReadRequestSize: schema.maybe(schema.string()), // byte value + maxWriteRequestOperationCount: schema.maybe(schema.number()), + maxWriteRequestSize: schema.maybe(schema.string()), // byte value + maxOutstandingWriteRequests: schema.maybe(schema.number()), + maxWriteBufferCount: schema.maybe(schema.number()), + maxWriteBufferSize: schema.maybe(schema.string()), // byte value + maxRetryDelay: schema.maybe(schema.string()), // time value + readPollTimeout: schema.maybe(schema.string()), // time value + }), }, }, licensePreRoutingFactory({ diff --git a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.helpers.js b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.helpers.js index dbcb6bf819749..294db29f6dce4 100644 --- a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.helpers.js +++ b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.helpers.js @@ -13,7 +13,45 @@ export const registerHelpers = supertest => { const loadFollowerIndices = () => supertest.get(`${API_BASE_PATH}/follower_indices`); - const getFollowerIndex = name => supertest.get(`${API_BASE_PATH}/follower_indices/${name}`); + const getFollowerIndex = (name, waitUntilIsActive = false) => { + const maxRetries = 10; + const delayBetweenRetries = 500; + let retryCount = 0; + + const proceed = async () => { + const response = await supertest.get(`${API_BASE_PATH}/follower_indices/${name}`); + + if (waitUntilIsActive && response.body.status !== 'active') { + retryCount += 1; + + if (retryCount > maxRetries) { + throw new Error('Error waiting for follower index to be active.'); + } + + return new Promise(resolve => setTimeout(resolve, delayBetweenRetries)).then(proceed); + } + + return response; + }; + + return { + expect: status => + new Promise((resolve, reject) => + proceed() + .then(response => { + if (status !== response.status) { + reject(new Error(`Expected status ${status} but got ${response.status}`)); + } + return resolve(response); + }) + .catch(reject) + ), + then: (resolve, reject) => + proceed() + .then(resolve) + .catch(reject), + }; + }; const createFollowerIndex = (name = getRandomString(), payload = getFollowerIndexPayload()) => { followerIndicesCreated.push(name); @@ -24,6 +62,13 @@ export const registerHelpers = supertest => { .send({ ...payload, name }); }; + const updateFollowerIndex = (name, payload) => { + return supertest + .put(`${API_BASE_PATH}/follower_indices/${name}`) + .set('kbn-xsrf', 'xxx') + .send(payload); + }; + const unfollowLeaderIndex = followerIndex => { const followerIndices = Array.isArray(followerIndex) ? followerIndex : [followerIndex]; const followerIndicesToEncodedString = followerIndices @@ -51,6 +96,7 @@ export const registerHelpers = supertest => { loadFollowerIndices, getFollowerIndex, createFollowerIndex, + updateFollowerIndex, unfollowAll, }; }; diff --git a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js index 5f9ebbd2a0a3f..eabf474120f2b 100644 --- a/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js +++ b/x-pack/test/api_integration/apis/management/cross_cluster_replication/follower_indices.js @@ -21,6 +21,7 @@ export default function({ getService }) { loadFollowerIndices, getFollowerIndex, createFollowerIndex, + updateFollowerIndex, unfollowAll, } = registerFollowerIndicesnHelpers(supertest); @@ -92,6 +93,31 @@ export default function({ getService }) { }); }); + describe('update()', () => { + it('should update a follower index advanced settings', async () => { + // Create a follower index + const leaderIndex = await createIndex(); + const followerIndex = getRandomString(); + const initialValue = 1234; + const payload = getFollowerIndexPayload(leaderIndex, undefined, { + maxReadRequestOperationCount: initialValue, + }); + await createFollowerIndex(followerIndex, payload); + + // Verify that its advanced settings are correctly set + const { body } = await getFollowerIndex(followerIndex, true); + expect(body.maxReadRequestOperationCount).to.be(initialValue); + + // Update the follower index + const updatedValue = 7777; + await updateFollowerIndex(followerIndex, { maxReadRequestOperationCount: updatedValue }); + + // Verify that the advanced settings are updated + const { body: updatedBody } = await getFollowerIndex(followerIndex, true); + expect(updatedBody.maxReadRequestOperationCount).to.be(updatedValue); + }); + }); + describe('Advanced settings', () => { it('hard-coded values should match Elasticsearch default values', async () => { /**