Add support for ccr follow info api to HLRC. (#39115)

This API was introduces after #33824 was closed.
This commit is contained in:
Martijn van Groningen 2019-02-20 15:37:40 +01:00
parent 48984f647d
commit 0594a467f2
No known key found for this signature in database
GPG Key ID: AB236F4FCF2AF12A
11 changed files with 595 additions and 0 deletions

View File

@ -23,6 +23,8 @@ import org.elasticsearch.action.ActionListener;
import org.elasticsearch.client.ccr.CcrStatsRequest; import org.elasticsearch.client.ccr.CcrStatsRequest;
import org.elasticsearch.client.ccr.CcrStatsResponse; import org.elasticsearch.client.ccr.CcrStatsResponse;
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest; 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.FollowStatsRequest;
import org.elasticsearch.client.ccr.FollowStatsResponse; import org.elasticsearch.client.ccr.FollowStatsResponse;
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest; import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
@ -452,4 +454,46 @@ public final class CcrClient {
); );
} }
/**
* Gets follow info for specific indices.
*
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-get-follow-info.html">
* the docs</a> 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 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/ccr-get-follow-info.html">
* the docs</a> 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<FollowInfoResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(
request,
CcrRequestConverters::getFollowInfo,
options,
FollowInfoResponse::fromXContent,
listener,
Collections.emptySet()
);
}
} }

View File

@ -25,6 +25,7 @@ import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut; import org.apache.http.client.methods.HttpPut;
import org.elasticsearch.client.ccr.CcrStatsRequest; import org.elasticsearch.client.ccr.CcrStatsRequest;
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest; import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest;
import org.elasticsearch.client.ccr.FollowInfoRequest;
import org.elasticsearch.client.ccr.FollowStatsRequest; import org.elasticsearch.client.ccr.FollowStatsRequest;
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest; import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
import org.elasticsearch.client.ccr.PauseFollowRequest; import org.elasticsearch.client.ccr.PauseFollowRequest;
@ -119,4 +120,12 @@ final class CcrRequestConverters {
return new Request(HttpGet.METHOD_NAME, endpoint); 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);
}
} }

View File

@ -22,8 +22,10 @@ package org.elasticsearch.client.ccr;
import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; 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 MAX_RETRY_DELAY_FIELD = new ParseField("max_retry_delay");
static final ParseField READ_POLL_TIMEOUT = new ParseField("read_poll_timeout"); static final ParseField READ_POLL_TIMEOUT = new ParseField("read_poll_timeout");
private static final ObjectParser<FollowConfig, Void> 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 maxReadRequestOperationCount;
private Integer maxOutstandingReadRequests; private Integer maxOutstandingReadRequests;
private ByteSizeValue maxReadRequestSize; private ByteSizeValue maxReadRequestSize;

View File

@ -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;
}
}

View File

@ -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<FollowInfoResponse, Void> PARSER = new ConstructingObjectParser<>(
"indices",
true,
args -> {
@SuppressWarnings("unchecked")
List<FollowerInfo> infos = (List<FollowerInfo>) 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<FollowerInfo> infos;
FollowInfoResponse(List<FollowerInfo> infos) {
this.infos = infos;
}
public List<FollowerInfo> 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<FollowerInfo, Void> 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 + "]");
}
}
}
}

View File

@ -32,6 +32,8 @@ import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.client.ccr.CcrStatsRequest; import org.elasticsearch.client.ccr.CcrStatsRequest;
import org.elasticsearch.client.ccr.CcrStatsResponse; import org.elasticsearch.client.ccr.CcrStatsResponse;
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest; 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.FollowStatsRequest;
import org.elasticsearch.client.ccr.FollowStatsResponse; import org.elasticsearch.client.ccr.FollowStatsResponse;
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest; import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
@ -113,6 +115,15 @@ public class CCRIT extends ESRestHighLevelClientTestCase {
try { try {
assertBusy(() -> { 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"); FollowStatsRequest followStatsRequest = new FollowStatsRequest("follower");
FollowStatsResponse followStatsResponse = FollowStatsResponse followStatsResponse =
execute(followStatsRequest, ccrClient::getFollowStats, ccrClient::getFollowStatsAsync); execute(followStatsRequest, ccrClient::getFollowStats, ccrClient::getFollowStatsAsync);
@ -170,6 +181,17 @@ public class CCRIT extends ESRestHighLevelClientTestCase {
pauseFollowResponse = execute(pauseFollowRequest, ccrClient::pauseFollow, ccrClient::pauseFollowAsync); pauseFollowResponse = execute(pauseFollowRequest, ccrClient::pauseFollow, ccrClient::pauseFollowAsync);
assertThat(pauseFollowResponse.isAcknowledged(), is(true)); 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: // Need to close index prior to unfollowing it:
CloseIndexRequest closeIndexRequest = new CloseIndexRequest("follower"); CloseIndexRequest closeIndexRequest = new CloseIndexRequest("follower");
org.elasticsearch.action.support.master.AcknowledgedResponse closeIndexReponse = org.elasticsearch.action.support.master.AcknowledgedResponse closeIndexReponse =

View File

@ -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;
}
}

View File

@ -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<FollowerInfo> 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);
}
}

View File

@ -36,6 +36,8 @@ import org.elasticsearch.client.ccr.AutoFollowStats;
import org.elasticsearch.client.ccr.CcrStatsRequest; import org.elasticsearch.client.ccr.CcrStatsRequest;
import org.elasticsearch.client.ccr.CcrStatsResponse; import org.elasticsearch.client.ccr.CcrStatsResponse;
import org.elasticsearch.client.ccr.DeleteAutoFollowPatternRequest; 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.FollowStatsRequest;
import org.elasticsearch.client.ccr.FollowStatsResponse; import org.elasticsearch.client.ccr.FollowStatsResponse;
import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest; import org.elasticsearch.client.ccr.GetAutoFollowPatternRequest;
@ -58,6 +60,7 @@ import org.junit.Before;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; 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<FollowInfoResponse.FollowerInfo> infos =
response.getInfos(); // <1>
// end::ccr-get-follow-info-response
// tag::ccr-get-follow-info-execute-listener
ActionListener<FollowInfoResponse> listener =
new ActionListener<FollowInfoResponse>() {
@Override
public void onResponse(FollowInfoResponse response) { // <1>
List<FollowInfoResponse.FollowerInfo> 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<String, Object> toMap(Response response) throws IOException { static Map<String, Object> toMap(Response response) throws IOException {
return XContentHelper.convertToMap(JsonXContent.jsonXContent, EntityUtils.toString(response.getEntity()), false); return XContentHelper.convertToMap(JsonXContent.jsonXContent, EntityUtils.toString(response.getEntity()), false);
} }

View File

@ -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[]

View File

@ -507,6 +507,7 @@ The Java High Level REST Client supports the following CCR APIs:
* <<{upid}-ccr-get-auto-follow-pattern>> * <<{upid}-ccr-get-auto-follow-pattern>>
* <<{upid}-ccr-get-stats>> * <<{upid}-ccr-get-stats>>
* <<{upid}-ccr-get-follow-stats>> * <<{upid}-ccr-get-follow-stats>>
* <<{upid}-ccr-get-follow-info>>
include::ccr/put_follow.asciidoc[] include::ccr/put_follow.asciidoc[]
include::ccr/pause_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_auto_follow_pattern.asciidoc[]
include::ccr/get_stats.asciidoc[] include::ccr/get_stats.asciidoc[]
include::ccr/get_follow_stats.asciidoc[] include::ccr/get_follow_stats.asciidoc[]
include::ccr/get_follow_info.asciidoc[]
== Index Lifecycle Management APIs == Index Lifecycle Management APIs