Skip to content

Commit 8557222

Browse files
authored
[6.x] [CCR] Follower index CRUD (#27936) (#30148)
* [CCR] Follower index CRUD (#27936) * [CCR] Refactor redux for Auto-follow pattern detail panel (#27491) * [CCR] Refactor redux for Auto-follow pattern detail panel * [CCR] Small refactor * [CCR] Change to present tense * [CCR] Display auto-follow pattern name even if it does not exist * [CCR] Use href to edit auto-follow pattern + remove middelware to update "pattern" query params * [CCR] Fix navigation back bug + set 2 ids for detail and edit an auto-follow pattern * [CCR] Replace api middleware with redux-thunk action * [CCR] Show detail footer close button even when cluster is not valid * [CCR] Add endpoints for fetching and creating follower indices (#27646) * Add GET /follower_indices endpoint with deserialization logic and tests. * Add POST /follower_indices endpoint with serialization logic and tests. * [CCR] Add unit tests for RemoteClusterForm, RemoteClusterList, and RemoteClusterTable (#27647) * Use componentDidUpdate instead of getDerivedStateFromProps. * Add unit tests for RemoteClusterForm, RemoteClusterList, and RemoteClusterTable. * Add jest mock for eui `makeId()` utility and get deterministic aria IDs for snapshots * Update snapshot for Remote Cluster list test * [CCR] Follower indices table and detail panel (#27804) * Store for follower indices * Initial work for follower indices table and detail panel * Fix load auto-follow stats load as middleware was removed * [CCR] Create follower index UI form (#27864) * Initial setup Follower Index form * Working form without client validation * Add client side validation for follower index * Add client validation to check if index already exist * Improve error message when leader index does not exist * Remove update method for follower index * Clear api error on field change * Fix i18n error * Update snapshots * [CCR] Add pause, resume, and unfollow actions for follower indices (#28305) * Add pause and resume follower index routes * Add unfollow route * Add api methods for new routes * Adjust routes to have bulk capabilities, add corresponding actions * Refresh list after pausing/resuming, remove items after unfollowing * First pass at UI for pause and unfollow (and resume, but that is not visible due to ES stats response) * Handle additional conditions needed for unfollowing leader index, add placeholder code to deduce paused status * PR feedback * [CCR] Advanced settings UI for follower indices (#28267) * Add client side validation of advanced settings form * Move form entry row to separate component * Add server side serialization for advanced settings * Ignore advanced settings input when that section is hidden. - Cache and restore input when the section is shown again. * [CCR] Show remote cluster validation in CCR forms, and add edit follower index (#28778) * [CCR] Advanced settings component * Remove preview active on toggle settings * Add client side validation of advanced settings form * Move form entry row to separate component * Add title to panel * Add i18n translation of advanced settings * Update Follower index form with toggle for advanced settings * Add server side serialisation for advanced settings * Make code review changes * Fix test: mock constant dependency * Add section to edit follower index * Show confirm modal before updating follower index * Add edit icon in table + update server endpoint to pause / resume * [CCR] Show remote cluster validation in follower index form & auto-follow pattern form * PR feedback, cleanup form sizes, add redirect to edit remote cluster * Fix routing, remove unused code, adjust auto follow pattern edit loading error page * Adjust error messages and make remote cluster not found edit page the same * Fix functionality as result of merge * Fix validation, reorder actions, fix tests, and address feedback * PR feedback and fix validation pt 2 * Adjust remote cluster validation * Fix i18n * Fix api error not showing on add follower form * [CCR] Integrate new follower index info ES API (#29153) * Integrate new follower index info ES API * Collate data from follower stats and info apis when retrieving all followers and single follower * Add follower settings info to detail panel * Add paused/active UI state * Surface follower default settings to UI * Adjust tests * Address PR feedback * Update snapshots * [CCR] Surface license errors in-app and refine permissions error UI. (#29228) * Fix camelcasing bug in XPackInfo. * Silently swallow API error when checking for index name availability. * Fix typo in followerIndexForm fatal error. * Add permissions check before allowing user to access the app. * Refine wording of CCR permission denied page, to specify cluster privileges. (#29533) * [CCR] Improve form error handling and general UX (#29419) * Remove unnecessary eslint disable-line * [CCR] Implement Advanced Settings design feedback (#29543) * Use EuiSwitch to toggle advanced settings in Create Follower Index form. * Move 'optional' from each Advanced Setting field to the section heading. * Change Advanced Settings switch label and description to emphasize that you can customize them or use the defaults. * Prepopulate Advanced Settings fields with default values. * When editing a follower index, check if advanced settings have been edited and open them if so. * Add 'Reset to default' button below advanced settings fields if their values are different than the default. * Remove 'Default' copy from Advanced Settings descriptions. * Simplify toggleAdvancedSettings function, add comments, and fix React console error. * [CCR] Follower index list fixes from design feedback (#29484) * Delete remote cluster settings before updating * Fix detail panel z-index * Remove default descriptor from follower index detail panel setting values * Follower index confirm action copy adjustments * Change z-index styling to use EUI vars * [CCR] Improve remote clusters test coverage (#29487) * Add Jest test for RemoteClusterForm validation state. * Extract validation functions out of RemoteClusterForm and add unit tests. - Return null instead of undefined from validators. * Add unit tests for different types of remote clusters in RemoteClusterTable. * Add unit test for RemoteClusterList empty prompt. * Add tests verifying behavior for row link, row delete button, and detail panel delete button. - Use getRouterLinkProps to assign onClick and href to edit buttons in row and detail panel. * [CCR] Adjust spacing around descriptions in list views, link to transport port docs, etc (#29789) * Adjust spacing around description around descriptions in list views so that it's even on top and bottom. * Add link to transport port docs from Remote Cluster form. * Move 'View in Index Management' link from the detail panel body into the footer. * Re-order follower index form sections: remote cluster, leader index, follower index. (#29885) * Fix deep-linking to follower index after creating/updating it. (#29865) * [CCR] Copy edits (#29676) * Use 'Resume/pause data replication' in context menu and row actions. * Update copy of 'Update' confirm modal for a paused follower index. * Update copy of 'Update' confirm modal for an active follower index. * Update copy of 'Pause data replication' confirm modal. * Update copy of 'Resume data replication' confirm modal. * Update copy for permissions check. * Update copy of table empty state. * Update copy around tables. * Update form copy. * Update copy for RemoteClustersFormField callouts. * Convert 'data replication' -> 'replication'. * Update copy for Unfollow confirm modal. * Update copy for form API error and Auto-follow Patterns table. * Update form save button labels to be 'Create' and 'Update'. * Move API errors to bottom of form, into same position as sync validation errors. Remove spacer from SectionError implementation. * [CCR] Open index after unfollowing leader (#29887) * Open index after unfollowing leader, fix some variable names * Fix typo * Add comment * [CCR] IE and Screen reader accesibility (#29731) * Fix api endpoit for auto-follow stats * Prevent letter wrapping in IE for the Remote cluster "connection" table column * Move inline style to CSS class to fix IE flex bug * [CCR] Add callout to paused follower index detail panel (#30013) * Add callout to paused follower index detail panel * Update copy * Skip call to ccr stats api if follower index is paused (#30027) * [CCR] Add integration tests for follower indices (#30064) * [CCR] Add integration tests for follower indices * Import advanced settings value from app constants * Disable flaky follower indices API integration tests.
1 parent cde31bf commit 8557222

File tree

129 files changed

+8865
-1213
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

129 files changed

+8865
-1213
lines changed

src/ui/public/indices/constants/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,9 @@
1919

2020
import { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE } from 'ui/index_patterns';
2121

22-
export const INDEX_ILLEGAL_CHARACTERS_VISIBLE = INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE.concat(',');
22+
export const INDEX_ILLEGAL_CHARACTERS_VISIBLE = [ ...INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE ];
23+
24+
// Insert the comma into the middle, so it doesn't look as if it has grammatical meaning when
25+
// these characters are rendered in the UI.
26+
const insertionIndex = Math.floor(INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE.length / 2);
27+
INDEX_ILLEGAL_CHARACTERS_VISIBLE.splice(insertionIndex, 0, ',');

x-pack/plugins/cross_cluster_replication/common/constants/base_path.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ export const BASE_PATH = '/management/elasticsearch/cross_cluster_replication';
88
export const BASE_PATH_REMOTE_CLUSTERS = '/management/elasticsearch/remote_clusters';
99
export const API_BASE_PATH = '/api/cross_cluster_replication';
1010
export const API_REMOTE_CLUSTERS_BASE_PATH = '/api/remote_clusters';
11+
export const API_INDEX_MANAGEMENT_BASE_PATH = '/api/index_management';

x-pack/plugins/cross_cluster_replication/common/constants/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
export * from './plugin';
88
export * from './base_path';
99
export * from './app';
10+
export * from './settings';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
export const FOLLOWER_INDEX_ADVANCED_SETTINGS = {
8+
maxReadRequestOperationCount: 5120,
9+
maxOutstandingReadRequests: 12,
10+
maxReadRequestSize: '32mb',
11+
maxWriteRequestOperationCount: 5120,
12+
maxWriteRequestSize: '9223372036854775807b',
13+
maxOutstandingWriteRequests: 9,
14+
maxWriteBufferCount: 2147483647,
15+
maxWriteBufferSize: '512mb',
16+
maxRetryDelay: '500ms',
17+
readPollTimeout: '1m',
18+
};

x-pack/plugins/cross_cluster_replication/common/services/utils.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,15 @@ export const wait = (time = 1000) => (data) => {
1515
setTimeout(() => resolve(data), time);
1616
});
1717
};
18+
19+
/**
20+
* Utility to remove empty fields ("") from a request body
21+
*/
22+
export const removeEmptyFields = (body) => (
23+
Object.entries(body).reduce((acc, [key, value]) => {
24+
if (value !== '') {
25+
acc[key] = value;
26+
}
27+
return acc;
28+
}, {})
29+
);
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
const Chance = require('chance'); // eslint-disable-line import/no-extraneous-dependencies
8+
const chance = new Chance();
9+
10+
export const getFollowerIndexStatsMock = (
11+
name = chance.string(),
12+
shards = [{
13+
id: chance.string(),
14+
remoteCluster: chance.string(),
15+
leaderIndex: chance.string(),
16+
leaderGlobalCheckpoint: chance.integer(),
17+
leaderMaxSequenceNum: chance.integer(),
18+
followerGlobalCheckpoint: chance.integer(),
19+
followerMaxSequenceNum: chance.integer(),
20+
lastRequestedSequenceNum: chance.integer(),
21+
outstandingReadRequestsCount: chance.integer(),
22+
outstandingWriteRequestsCount: chance.integer(),
23+
writeBufferOperationsCount: chance.integer(),
24+
writeBufferSizeBytes: chance.integer(),
25+
followerMappingVersion: chance.integer(),
26+
followerSettingsVersion: chance.integer(),
27+
totalReadTimeMs: chance.integer(),
28+
totalReadRemoteExecTimeMs: chance.integer(),
29+
successfulReadRequestCount: chance.integer(),
30+
failedReadRequestsCount: chance.integer(),
31+
operationsReadCount: chance.integer(),
32+
bytesReadCount: chance.integer(),
33+
totalWriteTimeMs: chance.integer(),
34+
successfulWriteRequestsCount: chance.integer(),
35+
failedWriteRequestsCount: chance.integer(),
36+
operationsWrittenCount: chance.integer(),
37+
readExceptions: [ chance.string() ],
38+
timeSinceLastReadMs: chance.integer(),
39+
}]
40+
) => {
41+
const serializeShard = ({
42+
id,
43+
remoteCluster,
44+
leaderIndex,
45+
leaderGlobalCheckpoint,
46+
leaderMaxSequenceNum,
47+
followerGlobalCheckpoint,
48+
followerMaxSequenceNum,
49+
lastRequestedSequenceNum,
50+
outstandingReadRequestsCount,
51+
outstandingWriteRequestsCount,
52+
writeBufferOperationsCount,
53+
writeBufferSizeBytes,
54+
followerMappingVersion,
55+
followerSettingsVersion,
56+
totalReadTimeMs,
57+
totalReadRemoteExecTimeMs,
58+
successfulReadRequestCount,
59+
failedReadRequestsCount,
60+
operationsReadCount,
61+
bytesReadCount,
62+
totalWriteTimeMs,
63+
successfulWriteRequestsCount,
64+
failedWriteRequestsCount,
65+
operationsWrittenCount,
66+
readExceptions,
67+
timeSinceLastReadMs,
68+
}) => ({
69+
shard_id: id,
70+
remote_cluster: remoteCluster,
71+
leader_index: leaderIndex,
72+
leader_global_checkpoint: leaderGlobalCheckpoint,
73+
leader_max_seq_no: leaderMaxSequenceNum,
74+
follower_global_checkpoint: followerGlobalCheckpoint,
75+
follower_max_seq_no: followerMaxSequenceNum,
76+
last_requested_seq_no: lastRequestedSequenceNum,
77+
outstanding_read_requests: outstandingReadRequestsCount,
78+
outstanding_write_requests: outstandingWriteRequestsCount,
79+
write_buffer_operation_count: writeBufferOperationsCount,
80+
write_buffer_size_in_bytes: writeBufferSizeBytes,
81+
follower_mapping_version: followerMappingVersion,
82+
follower_settings_version: followerSettingsVersion,
83+
total_read_time_millis: totalReadTimeMs,
84+
total_read_remote_exec_time_millis: totalReadRemoteExecTimeMs,
85+
successful_read_requests: successfulReadRequestCount,
86+
failed_read_requests: failedReadRequestsCount,
87+
operations_read: operationsReadCount,
88+
bytes_read: bytesReadCount,
89+
total_write_time_millis: totalWriteTimeMs,
90+
successful_write_requests: successfulWriteRequestsCount,
91+
failed_write_requests: failedWriteRequestsCount,
92+
operations_written: operationsWrittenCount,
93+
read_exceptions: readExceptions,
94+
time_since_last_read_millis: timeSinceLastReadMs,
95+
});
96+
97+
return {
98+
index: name,
99+
shards: shards.map(serializeShard),
100+
};
101+
};
102+
103+
export const getFollowerIndexListStatsMock = (total = 3, names) => {
104+
const list = {
105+
follow_stats: {
106+
indices: [],
107+
},
108+
};
109+
110+
for(let i = 0; i < total; i++) {
111+
list.follow_stats.indices.push(getFollowerIndexStatsMock(names[i]));
112+
}
113+
114+
return list;
115+
};
116+
117+
export const getFollowerIndexInfoMock = (
118+
name = chance.string(),
119+
status = chance.string(),
120+
parameters = {
121+
maxReadRequestOperationCount: chance.string(),
122+
maxOutstandingReadRequests: chance.string(),
123+
maxReadRequestSize: chance.string(),
124+
maxWriteRequestOperationCount: chance.string(),
125+
maxWriteRequestSize: chance.string(),
126+
maxOutstandingWriteRequests: chance.string(),
127+
maxWriteBufferCount: chance.string(),
128+
maxWriteBufferSize: chance.string(),
129+
maxRetryDelay: chance.string(),
130+
readPollTimeout: chance.string(),
131+
}
132+
) => {
133+
return {
134+
follower_index: name,
135+
status,
136+
max_read_request_operation_count: parameters.maxReadRequestOperationCount,
137+
max_outstanding_read_requests: parameters.maxOutstandingReadRequests,
138+
max_read_request_size: parameters.maxReadRequestSize,
139+
max_write_request_operation_count: parameters.maxWriteRequestOperationCount,
140+
max_write_request_size: parameters.maxWriteRequestSize,
141+
max_outstanding_write_requests: parameters.maxOutstandingWriteRequests,
142+
max_write_buffer_count: parameters.maxWriteBufferCount,
143+
max_write_buffer_size: parameters.maxWriteBufferSize,
144+
max_retry_delay: parameters.maxRetryDelay,
145+
read_poll_timeout: parameters.readPollTimeout,
146+
};
147+
};
148+
149+
export const getFollowerIndexListInfoMock = (total = 3) => {
150+
const list = {
151+
follower_indices: [],
152+
};
153+
154+
for(let i = 0; i < total; i++) {
155+
list.follower_indices.push(getFollowerIndexInfoMock());
156+
}
157+
158+
return list;
159+
};

x-pack/plugins/cross_cluster_replication/fixtures/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,10 @@ export {
1010
} from './auto_follow_pattern';
1111

1212
export { esErrors } from './es_errors';
13+
14+
export {
15+
getFollowerIndexStatsMock,
16+
getFollowerIndexListStatsMock,
17+
getFollowerIndexInfoMock,
18+
getFollowerIndexListInfoMock,
19+
} from './follower_index';

x-pack/plugins/cross_cluster_replication/public/app/_app.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,10 @@
55
.ccrFollowerIndicesHelpText {
66
transform: translateY(-3px);
77
}
8+
9+
/**
10+
* 1. Prevent context menu popover appearing above confirmation modal
11+
*/
12+
.ccrFollowerIndicesDetailPanel {
13+
z-index: $euiZMask - 1; /* 1 */
14+
}

0 commit comments

Comments
 (0)