diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/CcrClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/CcrClient.java
index 9a17dabf395..b6c68669667 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/CcrClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/CcrClient.java
@@ -23,6 +23,8 @@ import org.elasticsearch.action.ActionListener;
import org.elasticsearch.client.ccr.CcrStatsRequest;
import org.elasticsearch.client.ccr.CcrStatsResponse;
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
+import org.elasticsearch.client.ccr.FollowInfoRequest;
+import org.elasticsearch.client.ccr.FollowInfoResponse;
import org.elasticsearch.client.ccr.FollowStatsRequest;
import org.elasticsearch.client.ccr.FollowStatsResponse;
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
@@ -452,4 +454,46 @@ public final class CcrClient {
);
}
+ /**
+ * Gets follow info for specific indices.
+ *
+ * See
+ * the docs for more.
+ *
+ * @param request the request
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @return the response
+ * @throws IOException in case there is a problem sending the request or parsing back the response
+ */
+ public FollowInfoResponse getFollowInfo(FollowInfoRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(
+ request,
+ CcrRequestConverters::getFollowInfo,
+ options,
+ FollowInfoResponse::fromXContent,
+ Collections.emptySet()
+ );
+ }
+
+ /**
+ * Asynchronously gets follow info for specific indices.
+ *
+ * See
+ * the docs for more.
+ *
+ * @param request the request
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ */
+ public void getFollowInfoAsync(FollowInfoRequest request,
+ RequestOptions options,
+ ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(
+ request,
+ CcrRequestConverters::getFollowInfo,
+ options,
+ FollowInfoResponse::fromXContent,
+ listener,
+ Collections.emptySet()
+ );
+ }
}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/CcrRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/CcrRequestConverters.java
index 526db2a86a7..2e05aee9d75 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/CcrRequestConverters.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/CcrRequestConverters.java
@@ -25,6 +25,7 @@ import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.elasticsearch.client.ccr.CcrStatsRequest;
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
+import org.elasticsearch.client.ccr.FollowInfoRequest;
import org.elasticsearch.client.ccr.FollowStatsRequest;
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
import org.elasticsearch.client.ccr.PauseFollowRequest;
@@ -119,4 +120,12 @@ final class CcrRequestConverters {
return new Request(HttpGet.METHOD_NAME, endpoint);
}
+ static Request getFollowInfo(FollowInfoRequest followInfoRequest) {
+ String endpoint = new RequestConverters.EndpointBuilder()
+ .addPathPart(followInfoRequest.getFollowerIndex())
+ .addPathPartAsIs("_ccr", "info")
+ .build();
+ return new Request(HttpGet.METHOD_NAME, endpoint);
+ }
+
}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/FollowConfig.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/FollowConfig.java
index eb9b5e80767..37b0c5fa2c5 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/FollowConfig.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/FollowConfig.java
@@ -22,8 +22,10 @@ package org.elasticsearch.client.ccr;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.Objects;
@@ -41,6 +43,44 @@ public class FollowConfig {
static final ParseField MAX_RETRY_DELAY_FIELD = new ParseField("max_retry_delay");
static final ParseField READ_POLL_TIMEOUT = new ParseField("read_poll_timeout");
+ private static final ObjectParser PARSER = new ObjectParser<>(
+ "follow_config",
+ true,
+ FollowConfig::new);
+
+ static {
+ PARSER.declareInt(FollowConfig::setMaxReadRequestOperationCount, MAX_READ_REQUEST_OPERATION_COUNT);
+ PARSER.declareInt(FollowConfig::setMaxOutstandingReadRequests, MAX_OUTSTANDING_READ_REQUESTS);
+ PARSER.declareField(
+ FollowConfig::setMaxReadRequestSize,
+ (p, c) -> ByteSizeValue.parseBytesSizeValue(p.text(), MAX_READ_REQUEST_SIZE.getPreferredName()),
+ MAX_READ_REQUEST_SIZE,
+ ObjectParser.ValueType.STRING);
+ PARSER.declareInt(FollowConfig::setMaxWriteRequestOperationCount, MAX_WRITE_REQUEST_OPERATION_COUNT);
+ PARSER.declareField(
+ FollowConfig::setMaxWriteRequestSize,
+ (p, c) -> ByteSizeValue.parseBytesSizeValue(p.text(), MAX_WRITE_REQUEST_SIZE.getPreferredName()),
+ MAX_WRITE_REQUEST_SIZE,
+ ObjectParser.ValueType.STRING);
+ PARSER.declareInt(FollowConfig::setMaxOutstandingWriteRequests, MAX_OUTSTANDING_WRITE_REQUESTS);
+ PARSER.declareInt(FollowConfig::setMaxWriteBufferCount, MAX_WRITE_BUFFER_COUNT);
+ PARSER.declareField(
+ FollowConfig::setMaxWriteBufferSize,
+ (p, c) -> ByteSizeValue.parseBytesSizeValue(p.text(), MAX_WRITE_BUFFER_SIZE.getPreferredName()),
+ MAX_WRITE_BUFFER_SIZE,
+ ObjectParser.ValueType.STRING);
+ PARSER.declareField(FollowConfig::setMaxRetryDelay,
+ (p, c) -> TimeValue.parseTimeValue(p.text(), MAX_RETRY_DELAY_FIELD.getPreferredName()),
+ MAX_RETRY_DELAY_FIELD, ObjectParser.ValueType.STRING);
+ PARSER.declareField(FollowConfig::setReadPollTimeout,
+ (p, c) -> TimeValue.parseTimeValue(p.text(), READ_POLL_TIMEOUT.getPreferredName()),
+ READ_POLL_TIMEOUT, ObjectParser.ValueType.STRING);
+ }
+
+ static FollowConfig fromXContent(XContentParser parser) {
+ return PARSER.apply(parser, null);
+ }
+
private Integer maxReadRequestOperationCount;
private Integer maxOutstandingReadRequests;
private ByteSizeValue maxReadRequestSize;
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/FollowInfoRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/FollowInfoRequest.java
new file mode 100644
index 00000000000..3fe9136fcbd
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/FollowInfoRequest.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.
+ */
+
+package org.elasticsearch.client.ccr;
+
+import org.elasticsearch.client.Validatable;
+
+import java.util.Objects;
+
+public final class FollowInfoRequest implements Validatable {
+
+ private final String followerIndex;
+
+ public FollowInfoRequest(String followerIndex) {
+ this.followerIndex = Objects.requireNonNull(followerIndex);
+ }
+
+ public String getFollowerIndex() {
+ return followerIndex;
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/FollowInfoResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/FollowInfoResponse.java
new file mode 100644
index 00000000000..3e15db318a3
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/FollowInfoResponse.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.
+ */
+
+package org.elasticsearch.client.ccr;
+
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.util.List;
+import java.util.Objects;
+
+public final class FollowInfoResponse {
+
+ static final ParseField FOLLOWER_INDICES_FIELD = new ParseField("follower_indices");
+
+ private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "indices",
+ true,
+ args -> {
+ @SuppressWarnings("unchecked")
+ List infos = (List) args[0];
+ return new FollowInfoResponse(infos);
+ });
+
+ static {
+ PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), FollowerInfo.PARSER, FOLLOWER_INDICES_FIELD);
+ }
+
+ public static FollowInfoResponse fromXContent(XContentParser parser) {
+ return PARSER.apply(parser, null);
+ }
+
+ private final List infos;
+
+ FollowInfoResponse(List infos) {
+ this.infos = infos;
+ }
+
+ public List getInfos() {
+ return infos;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ FollowInfoResponse that = (FollowInfoResponse) o;
+ return infos.equals(that.infos);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(infos);
+ }
+
+ public static final class FollowerInfo {
+
+ static final ParseField FOLLOWER_INDEX_FIELD = new ParseField("follower_index");
+ static final ParseField REMOTE_CLUSTER_FIELD = new ParseField("remote_cluster");
+ static final ParseField LEADER_INDEX_FIELD = new ParseField("leader_index");
+ static final ParseField STATUS_FIELD = new ParseField("status");
+ static final ParseField PARAMETERS_FIELD = new ParseField("parameters");
+
+ private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "follower_info",
+ true,
+ args -> {
+ return new FollowerInfo((String) args[0], (String) args[1], (String) args[2],
+ Status.fromString((String) args[3]), (FollowConfig) args[4]);
+ });
+
+ static {
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), FOLLOWER_INDEX_FIELD);
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), REMOTE_CLUSTER_FIELD);
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), LEADER_INDEX_FIELD);
+ PARSER.declareString(ConstructingObjectParser.constructorArg(), STATUS_FIELD);
+ PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(),
+ (p, c) -> FollowConfig.fromXContent(p), PARAMETERS_FIELD);
+ }
+
+ private final String followerIndex;
+ private final String remoteCluster;
+ private final String leaderIndex;
+ private final Status status;
+ private final FollowConfig parameters;
+
+ FollowerInfo(String followerIndex, String remoteCluster, String leaderIndex, Status status,
+ FollowConfig parameters) {
+ this.followerIndex = followerIndex;
+ this.remoteCluster = remoteCluster;
+ this.leaderIndex = leaderIndex;
+ this.status = status;
+ this.parameters = parameters;
+ }
+
+ public String getFollowerIndex() {
+ return followerIndex;
+ }
+
+ public String getRemoteCluster() {
+ return remoteCluster;
+ }
+
+ public String getLeaderIndex() {
+ return leaderIndex;
+ }
+
+ public Status getStatus() {
+ return status;
+ }
+
+ public FollowConfig getParameters() {
+ return parameters;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ FollowerInfo that = (FollowerInfo) o;
+ return Objects.equals(followerIndex, that.followerIndex) &&
+ Objects.equals(remoteCluster, that.remoteCluster) &&
+ Objects.equals(leaderIndex, that.leaderIndex) &&
+ status == that.status &&
+ Objects.equals(parameters, that.parameters);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(followerIndex, remoteCluster, leaderIndex, status, parameters);
+ }
+
+ }
+
+ public enum Status {
+
+ ACTIVE("active"),
+ PAUSED("paused");
+
+ private final String name;
+
+ Status(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public static Status fromString(String value) {
+ switch (value) {
+ case "active":
+ return Status.ACTIVE;
+ case "paused":
+ return Status.PAUSED;
+ default:
+ throw new IllegalArgumentException("unexpected status value [" + value + "]");
+ }
+ }
+ }
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java
index ee2685dee6d..14e2f977e63 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java
@@ -32,6 +32,8 @@ import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.ccr.CcrStatsRequest;
import org.elasticsearch.client.ccr.CcrStatsResponse;
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
+import org.elasticsearch.client.ccr.FollowInfoRequest;
+import org.elasticsearch.client.ccr.FollowInfoResponse;
import org.elasticsearch.client.ccr.FollowStatsRequest;
import org.elasticsearch.client.ccr.FollowStatsResponse;
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
@@ -113,6 +115,15 @@ public class CCRIT extends ESRestHighLevelClientTestCase {
try {
assertBusy(() -> {
+ FollowInfoRequest followInfoRequest = new FollowInfoRequest("follower");
+ FollowInfoResponse followInfoResponse =
+ execute(followInfoRequest, ccrClient::getFollowInfo, ccrClient::getFollowInfoAsync);
+ assertThat(followInfoResponse.getInfos().size(), equalTo(1));
+ assertThat(followInfoResponse.getInfos().get(0).getFollowerIndex(), equalTo("follower"));
+ assertThat(followInfoResponse.getInfos().get(0).getLeaderIndex(), equalTo("leader"));
+ assertThat(followInfoResponse.getInfos().get(0).getRemoteCluster(), equalTo("local_cluster"));
+ assertThat(followInfoResponse.getInfos().get(0).getStatus(), equalTo(FollowInfoResponse.Status.ACTIVE));
+
FollowStatsRequest followStatsRequest = new FollowStatsRequest("follower");
FollowStatsResponse followStatsResponse =
execute(followStatsRequest, ccrClient::getFollowStats, ccrClient::getFollowStatsAsync);
@@ -170,6 +181,17 @@ public class CCRIT extends ESRestHighLevelClientTestCase {
pauseFollowResponse = execute(pauseFollowRequest, ccrClient::pauseFollow, ccrClient::pauseFollowAsync);
assertThat(pauseFollowResponse.isAcknowledged(), is(true));
+ assertBusy(() -> {
+ FollowInfoRequest followInfoRequest = new FollowInfoRequest("follower");
+ FollowInfoResponse followInfoResponse =
+ execute(followInfoRequest, ccrClient::getFollowInfo, ccrClient::getFollowInfoAsync);
+ assertThat(followInfoResponse.getInfos().size(), equalTo(1));
+ assertThat(followInfoResponse.getInfos().get(0).getFollowerIndex(), equalTo("follower"));
+ assertThat(followInfoResponse.getInfos().get(0).getLeaderIndex(), equalTo("leader"));
+ assertThat(followInfoResponse.getInfos().get(0).getRemoteCluster(), equalTo("local_cluster"));
+ assertThat(followInfoResponse.getInfos().get(0).getStatus(), equalTo(FollowInfoResponse.Status.PAUSED));
+ });
+
// Need to close index prior to unfollowing it:
CloseIndexRequest closeIndexRequest = new CloseIndexRequest("follower");
org.elasticsearch.action.support.master.AcknowledgedResponse closeIndexReponse =
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ccr/FollowConfigTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ccr/FollowConfigTests.java
new file mode 100644
index 00000000000..0d8b4ca8726
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ccr/FollowConfigTests.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.
+ */
+
+package org.elasticsearch.client.ccr;
+
+import org.elasticsearch.common.unit.ByteSizeValue;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.test.ESTestCase;
+
+import java.io.IOException;
+
+import static org.elasticsearch.test.AbstractXContentTestCase.xContentTester;
+
+public class FollowConfigTests extends ESTestCase {
+
+ public void testFromXContent() throws IOException {
+ xContentTester(this::createParser,
+ FollowConfigTests::createTestInstance,
+ (followConfig, xContentBuilder) -> {
+ xContentBuilder.startObject();
+ followConfig.toXContentFragment(xContentBuilder, ToXContent.EMPTY_PARAMS);
+ xContentBuilder.endObject();
+ },
+ FollowConfig::fromXContent)
+ .supportsUnknownFields(true)
+ .test();
+ }
+
+ static FollowConfig createTestInstance() {
+ FollowConfig followConfig = new FollowConfig();
+ if (randomBoolean()) {
+ followConfig.setMaxOutstandingReadRequests(randomIntBetween(0, Integer.MAX_VALUE));
+ }
+ if (randomBoolean()) {
+ followConfig.setMaxOutstandingWriteRequests(randomIntBetween(0, Integer.MAX_VALUE));
+ }
+ if (randomBoolean()) {
+ followConfig.setMaxReadRequestOperationCount(randomIntBetween(0, Integer.MAX_VALUE));
+ }
+ if (randomBoolean()) {
+ followConfig.setMaxReadRequestSize(new ByteSizeValue(randomNonNegativeLong()));
+ }
+ if (randomBoolean()) {
+ followConfig.setMaxWriteBufferCount(randomIntBetween(0, Integer.MAX_VALUE));
+ }
+ if (randomBoolean()) {
+ followConfig.setMaxWriteBufferSize(new ByteSizeValue(randomNonNegativeLong()));
+ }
+ if (randomBoolean()) {
+ followConfig.setMaxWriteRequestOperationCount(randomIntBetween(0, Integer.MAX_VALUE));
+ }
+ if (randomBoolean()) {
+ followConfig.setMaxWriteRequestSize(new ByteSizeValue(randomNonNegativeLong()));
+ }
+ if (randomBoolean()) {
+ followConfig.setMaxRetryDelay(new TimeValue(randomNonNegativeLong()));
+ }
+ if (randomBoolean()) {
+ followConfig.setReadPollTimeout(new TimeValue(randomNonNegativeLong()));
+ }
+ return followConfig;
+ }
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ccr/FollowInfoResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ccr/FollowInfoResponseTests.java
new file mode 100644
index 00000000000..5cd327495dc
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ccr/FollowInfoResponseTests.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.
+ */
+
+package org.elasticsearch.client.ccr;
+
+import org.elasticsearch.client.ccr.FollowInfoResponse.FollowerInfo;
+import org.elasticsearch.common.xcontent.ToXContent;
+import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.test.ESTestCase;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.elasticsearch.test.AbstractXContentTestCase.xContentTester;
+
+public class FollowInfoResponseTests extends ESTestCase {
+
+ public void testFromXContent() throws IOException {
+ xContentTester(this::createParser,
+ FollowInfoResponseTests::createTestInstance,
+ FollowInfoResponseTests::toXContent,
+ FollowInfoResponse::fromXContent)
+ .supportsUnknownFields(true)
+ .test();
+ }
+
+ private static void toXContent(FollowInfoResponse response, XContentBuilder builder) throws IOException {
+ builder.startObject();
+ builder.startArray(FollowInfoResponse.FOLLOWER_INDICES_FIELD.getPreferredName());
+ for (FollowerInfo info : response.getInfos()) {
+ builder.startObject();
+ builder.field(FollowerInfo.FOLLOWER_INDEX_FIELD.getPreferredName(), info.getFollowerIndex());
+ builder.field(FollowerInfo.REMOTE_CLUSTER_FIELD.getPreferredName(), info.getRemoteCluster());
+ builder.field(FollowerInfo.LEADER_INDEX_FIELD.getPreferredName(), info.getLeaderIndex());
+ builder.field(FollowerInfo.STATUS_FIELD.getPreferredName(), info.getStatus().getName());
+ if (info.getParameters() != null) {
+ builder.startObject(FollowerInfo.PARAMETERS_FIELD.getPreferredName());
+ {
+ info.getParameters().toXContentFragment(builder, ToXContent.EMPTY_PARAMS);
+ }
+ builder.endObject();
+ }
+ builder.endObject();
+ }
+ builder.endArray();
+ builder.endObject();
+ }
+
+ private static FollowInfoResponse createTestInstance() {
+ int numInfos = randomIntBetween(0, 64);
+ List infos = new ArrayList<>(numInfos);
+ for (int i = 0; i < numInfos; i++) {
+ FollowInfoResponse.Status status = randomFrom(FollowInfoResponse.Status.values());
+ FollowConfig followConfig = randomBoolean() ? FollowConfigTests.createTestInstance() : null;
+ infos.add(new FollowerInfo(randomAlphaOfLength(4), randomAlphaOfLength(4), randomAlphaOfLength(4), status, followConfig));
+ }
+ return new FollowInfoResponse(infos);
+ }
+
+}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CCRDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CCRDocumentationIT.java
index 2e54d1c4a1a..23cdd39787d 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CCRDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CCRDocumentationIT.java
@@ -36,6 +36,8 @@ import org.elasticsearch.client.ccr.AutoFollowStats;
import org.elasticsearch.client.ccr.CcrStatsRequest;
import org.elasticsearch.client.ccr.CcrStatsResponse;
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
+import org.elasticsearch.client.ccr.FollowInfoRequest;
+import org.elasticsearch.client.ccr.FollowInfoResponse;
import org.elasticsearch.client.ccr.FollowStatsRequest;
import org.elasticsearch.client.ccr.FollowStatsResponse;
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
@@ -58,6 +60,7 @@ import org.junit.Before;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -697,6 +700,74 @@ public class CCRDocumentationIT extends ESRestHighLevelClientTestCase {
}
}
+ public void testGetFollowInfos() throws Exception {
+ RestHighLevelClient client = highLevelClient();
+
+ {
+ // Create leader index:
+ CreateIndexRequest createIndexRequest = new CreateIndexRequest("leader");
+ createIndexRequest.settings(Collections.singletonMap("index.soft_deletes.enabled", true));
+ CreateIndexResponse response = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
+ assertThat(response.isAcknowledged(), is(true));
+ }
+ {
+ // Follow index, so that we can query for follow stats:
+ PutFollowRequest putFollowRequest = new PutFollowRequest("local", "leader", "follower", ActiveShardCount.ONE);
+ PutFollowResponse putFollowResponse = client.ccr().putFollow(putFollowRequest, RequestOptions.DEFAULT);
+ assertThat(putFollowResponse.isFollowIndexCreated(), is(true));
+ assertThat(putFollowResponse.isFollowIndexShardsAcked(), is(true));
+ assertThat(putFollowResponse.isIndexFollowingStarted(), is(true));
+ }
+
+ // tag::ccr-get-follow-info-request
+ FollowInfoRequest request =
+ new FollowInfoRequest("follower"); // <1>
+ // end::ccr-get-follow-info-request
+
+ // tag::ccr-get-follow-info-execute
+ FollowInfoResponse response = client.ccr()
+ .getFollowInfo(request, RequestOptions.DEFAULT);
+ // end::ccr-get-follow-info-execute
+
+ // tag::ccr-get-follow-info-response
+ List infos =
+ response.getInfos(); // <1>
+ // end::ccr-get-follow-info-response
+
+ // tag::ccr-get-follow-info-execute-listener
+ ActionListener listener =
+ new ActionListener() {
+ @Override
+ public void onResponse(FollowInfoResponse response) { // <1>
+ List infos =
+ response.getInfos();
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+ // <2>
+ }
+ };
+ // end::ccr-get-follow-info-execute-listener
+
+ // Replace the empty listener by a blocking listener in test
+ final CountDownLatch latch = new CountDownLatch(1);
+ listener = new LatchedActionListener<>(listener, latch);
+
+ // tag::ccr-get-follow-info-execute-async
+ client.ccr().getFollowInfoAsync(request,
+ RequestOptions.DEFAULT, listener); // <1>
+ // end::ccr-get-follow-info-execute-async
+
+ assertTrue(latch.await(30L, TimeUnit.SECONDS));
+
+ {
+ PauseFollowRequest pauseFollowRequest = new PauseFollowRequest("follower");
+ AcknowledgedResponse pauseFollowResponse = client.ccr().pauseFollow(pauseFollowRequest, RequestOptions.DEFAULT);
+ assertThat(pauseFollowResponse.isAcknowledged(), is(true));
+ }
+ }
+
static Map toMap(Response response) throws IOException {
return XContentHelper.convertToMap(JsonXContent.jsonXContent, EntityUtils.toString(response.getEntity()), false);
}
diff --git a/docs/java-rest/high-level/ccr/get_follow_info.asciidoc b/docs/java-rest/high-level/ccr/get_follow_info.asciidoc
new file mode 100644
index 00000000000..3d4e8d5456e
--- /dev/null
+++ b/docs/java-rest/high-level/ccr/get_follow_info.asciidoc
@@ -0,0 +1,35 @@
+--
+:api: ccr-get-follow-info
+:request: FollowInfoRequest
+:response: FollowInfoResponse
+--
+
+[id="{upid}-{api}"]
+=== Get Follow Info API
+
+
+[id="{upid}-{api}-request"]
+==== Request
+
+The Get Follow Info API allows you to get follow information (parameters and status) for specific follower indices.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-request]
+--------------------------------------------------
+<1> The follower index to get follow information for.
+
+[id="{upid}-{api}-response"]
+==== Response
+
+The returned +{response}+ includes follow information for the specified follower indices
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-response]
+--------------------------------------------------
+<1> The follow information for specified follower indices.
+
+include::../execution.asciidoc[]
+
+
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index 1df10985e7e..1f3bee46cc8 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -507,6 +507,7 @@ The Java High Level REST Client supports the following CCR APIs:
* <<{upid}-ccr-get-auto-follow-pattern>>
* <<{upid}-ccr-get-stats>>
* <<{upid}-ccr-get-follow-stats>>
+* <<{upid}-ccr-get-follow-info>>
include::ccr/put_follow.asciidoc[]
include::ccr/pause_follow.asciidoc[]
@@ -517,6 +518,7 @@ include::ccr/delete_auto_follow_pattern.asciidoc[]
include::ccr/get_auto_follow_pattern.asciidoc[]
include::ccr/get_stats.asciidoc[]
include::ccr/get_follow_stats.asciidoc[]
+include::ccr/get_follow_info.asciidoc[]
== Index Lifecycle Management APIs