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
new file mode 100644
index 0000000000000..2857ec970908a
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/CcrClient.java
@@ -0,0 +1,86 @@
+/*
+ * 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;
+
+import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.client.ccr.PauseFollowRequest;
+import org.elasticsearch.client.core.AcknowledgedResponse;
+
+import java.io.IOException;
+import java.util.Collections;
+
+/**
+ * A wrapper for the {@link RestHighLevelClient} that provides methods for
+ * accessing the Elastic ccr related methods
+ *
+ * See the
+ * X-Pack Rollup APIs on elastic.co for more information.
+ */
+public final class CcrClient {
+
+ private final RestHighLevelClient restHighLevelClient;
+
+ CcrClient(RestHighLevelClient restHighLevelClient) {
+ this.restHighLevelClient = restHighLevelClient;
+ }
+
+ /**
+ * Instructs a follower index the pause the following of a leader index.
+ *
+ * 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 AcknowledgedResponse pauseFollow(PauseFollowRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(
+ request,
+ CcrRequestConverters::pauseFollow,
+ options,
+ AcknowledgedResponse::fromXContent,
+ Collections.emptySet()
+ );
+ }
+
+ /**
+ * Asynchronously instruct a follower index the pause the following of a leader index.
+ *
+ * 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 pauseFollowAsync(PauseFollowRequest request,
+ RequestOptions options,
+ ActionListener listener) {
+ restHighLevelClient.performRequestAsyncAndParseEntity(
+ request,
+ CcrRequestConverters::pauseFollow,
+ options,
+ AcknowledgedResponse::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
new file mode 100644
index 0000000000000..c33ed5e4bf05d
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/CcrRequestConverters.java
@@ -0,0 +1,35 @@
+/*
+ * 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;
+
+import org.apache.http.client.methods.HttpPost;
+import org.elasticsearch.client.ccr.PauseFollowRequest;
+
+final class CcrRequestConverters {
+
+ static Request pauseFollow(PauseFollowRequest pauseFollowRequest) {
+ String endpoint = new RequestConverters.EndpointBuilder()
+ .addPathPart(pauseFollowRequest.getFollowerIndex())
+ .addPathPartAsIs("_ccr", "pause_follow")
+ .build();
+ return new Request(HttpPost.METHOD_NAME, endpoint);
+ }
+
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
index 11fff4c0a6b4d..582f917e43b38 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java
@@ -228,6 +228,7 @@ public class RestHighLevelClient implements Closeable {
private final SecurityClient securityClient = new SecurityClient(this);
private final IndexLifecycleClient ilmClient = new IndexLifecycleClient(this);
private final RollupClient rollupClient = new RollupClient(this);
+ private final CcrClient ccrClient = new CcrClient(this);
/**
* Creates a {@link RestHighLevelClient} given the low level {@link RestClientBuilder} that allows to build the
@@ -321,6 +322,20 @@ public RollupClient rollup() {
return rollupClient;
}
+ /**
+ * Provides methods for accessing the Elastic Licensed CCR APIs that
+ * are shipped with the Elastic Stack distribution of Elasticsearch. All of
+ * these APIs will 404 if run against the OSS distribution of Elasticsearch.
+ *
+ * See the
+ * CCR APIs on elastic.co for more information.
+ *
+ * @return the client wrapper for making CCR API calls
+ */
+ public final CcrClient ccr() {
+ return ccrClient;
+ }
+
/**
* Provides a {@link TasksClient} which can be used to access the Tasks API.
*
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/PauseFollowRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/PauseFollowRequest.java
new file mode 100644
index 0000000000000..44ac443542caf
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ccr/PauseFollowRequest.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 PauseFollowRequest implements Validatable {
+
+ private final String followerIndex;
+
+ public PauseFollowRequest(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/rollup/AcknowledgedResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/AcknowledgedResponse.java
similarity index 83%
rename from client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/AcknowledgedResponse.java
rename to client/rest-high-level/src/main/java/org/elasticsearch/client/core/AcknowledgedResponse.java
index 4e279844afc59..f46ea88d473d0 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/AcknowledgedResponse.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/core/AcknowledgedResponse.java
@@ -17,13 +17,14 @@
* under the License.
*/
-package org.elasticsearch.client.rollup;
+package org.elasticsearch.client.core;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.Objects;
@@ -31,9 +32,12 @@
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
-public abstract class AcknowledgedResponse implements ToXContentObject {
+public class AcknowledgedResponse implements ToXContentObject {
protected static final String PARSE_FIELD_NAME = "acknowledged";
+ private static final ConstructingObjectParser PARSER = AcknowledgedResponse
+ .generateParser("acknowledged_response", AcknowledgedResponse::new, AcknowledgedResponse.PARSE_FIELD_NAME);
+
private final boolean acknowledged;
public AcknowledgedResponse(final boolean acknowledged) {
@@ -50,6 +54,10 @@ protected static ConstructingObjectParser generateParser(String nam
return p;
}
+ public static AcknowledgedResponse fromXContent(final XContentParser parser) throws IOException {
+ return PARSER.parse(parser, null);
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/DeleteRollupJobResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/DeleteRollupJobResponse.java
index 35734c4a8358a..a4f2cd45a2a26 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/DeleteRollupJobResponse.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/DeleteRollupJobResponse.java
@@ -19,6 +19,7 @@
package org.elasticsearch.client.rollup;
+import org.elasticsearch.client.core.AcknowledgedResponse;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.XContentParser;
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/PutRollupJobResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/PutRollupJobResponse.java
index 31c656b033479..6a93f364c68e6 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/PutRollupJobResponse.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/PutRollupJobResponse.java
@@ -18,6 +18,7 @@
*/
package org.elasticsearch.client.rollup;
+import org.elasticsearch.client.core.AcknowledgedResponse;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.XContentParser;
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/StartRollupJobResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/StartRollupJobResponse.java
index b953901ce0c84..be388ba8bc3b7 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/StartRollupJobResponse.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/rollup/StartRollupJobResponse.java
@@ -19,6 +19,7 @@
package org.elasticsearch.client.rollup;
+import org.elasticsearch.client.core.AcknowledgedResponse;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.XContentParser;
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java
index 38810285a5d1c..dfb9848126de1 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java
@@ -785,7 +785,8 @@ public void testApiNamingConventions() throws Exception {
apiName.startsWith("graph.") == false &&
apiName.startsWith("migration.") == false &&
apiName.startsWith("security.") == false &&
- apiName.startsWith("index_lifecycle.") == false) {
+ apiName.startsWith("index_lifecycle.") == false &&
+ apiName.startsWith("ccr.") == false) {
apiNotFound.add(apiName);
}
}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/core/AcknowledgedResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/core/AcknowledgedResponseTests.java
new file mode 100644
index 0000000000000..36ba953073987
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/core/AcknowledgedResponseTests.java
@@ -0,0 +1,43 @@
+/*
+ * 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.core;
+
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.test.AbstractXContentTestCase;
+
+import java.io.IOException;
+
+public class AcknowledgedResponseTests extends AbstractXContentTestCase {
+
+ @Override
+ protected AcknowledgedResponse createTestInstance() {
+ return new AcknowledgedResponse(randomBoolean());
+ }
+
+ @Override
+ protected AcknowledgedResponse doParseInstance(XContentParser parser) throws IOException {
+ return AcknowledgedResponse.fromXContent(parser);
+ }
+
+ @Override
+ protected boolean supportsUnknownFields() {
+ return false;
+ }
+
+}
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
new file mode 100644
index 0000000000000..e61123f722f40
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/CCRDocumentationIT.java
@@ -0,0 +1,139 @@
+/*
+ * 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.documentation;
+
+import org.apache.http.util.EntityUtils;
+import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.LatchedActionListener;
+import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
+import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
+import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
+import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
+import org.elasticsearch.client.ESRestHighLevelClientTestCase;
+import org.elasticsearch.client.Request;
+import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.Response;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.ccr.PauseFollowRequest;
+import org.elasticsearch.client.core.AcknowledgedResponse;
+import org.elasticsearch.common.xcontent.XContentHelper;
+import org.elasticsearch.common.xcontent.json.JsonXContent;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+
+public class CCRDocumentationIT extends ESRestHighLevelClientTestCase {
+
+ public void testPauseFollow() throws Exception {
+ RestHighLevelClient client = highLevelClient();
+
+ {
+ // Configure local cluster as remote cluster:
+
+ // TODO: replace with nodes info highlevel rest client code when it is available:
+ final Request request = new Request("GET", "/_nodes");
+ Map, ?> nodesResponse = (Map, ?>) toMap(client().performRequest(request)).get("nodes");
+ // Select node info of first node (we don't know the node id):
+ nodesResponse = (Map, ?>) nodesResponse.get(nodesResponse.keySet().iterator().next());
+ String transportAddress = (String) nodesResponse.get("transport_address");
+
+ ClusterUpdateSettingsRequest updateSettingsRequest = new ClusterUpdateSettingsRequest();
+ updateSettingsRequest.transientSettings(Collections.singletonMap("cluster.remote.local.seeds", transportAddress));
+ ClusterUpdateSettingsResponse updateSettingsResponse =
+ client.cluster().putSettings(updateSettingsRequest, RequestOptions.DEFAULT);
+ assertThat(updateSettingsResponse.isAcknowledged(), is(true));
+ }
+ {
+ // 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));
+ }
+ String followIndex = "follower";
+ // Follow index, so that it can be paused:
+ {
+ // TODO: Replace this with high level rest client code when put follow API is available:
+ final Request request = new Request("PUT", "/" + followIndex + "/_ccr/follow");
+ request.setJsonEntity("{\"remote_cluster\": \"local\", \"leader_index\": \"leader\"}");
+ Response response = client().performRequest(request);
+ assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
+ }
+
+ // tag::ccr-pause-follow-request
+ PauseFollowRequest request = new PauseFollowRequest(followIndex); // <1>
+ // end::ccr-pause-follow-request
+
+ // tag::ccr-pause-follow-execute
+ AcknowledgedResponse response =
+ client.ccr().pauseFollow(request, RequestOptions.DEFAULT);
+ // end::ccr-pause-follow-execute
+
+ // tag::ccr-pause-follow-response
+ boolean acknowledged = response.isAcknowledged(); // <1>
+ // end::ccr-pause-follow-response
+
+ // tag::ccr-pause-follow-execute-listener
+ ActionListener listener =
+ new ActionListener() {
+ @Override
+ public void onResponse(AcknowledgedResponse response) {
+ boolean acknowledged = response.isAcknowledged(); // <1>
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+ // <2>
+ }
+ };
+ // end::ccr-pause-follow-execute-listener
+
+ // Resume follow index, so that it can be paused again:
+ {
+ // TODO: Replace this with high level rest client code when resume follow API is available:
+ final Request req = new Request("POST", "/" + followIndex + "/_ccr/resume_follow");
+ req.setJsonEntity("{}");
+ Response res = client().performRequest(req);
+ assertThat(res.getStatusLine().getStatusCode(), equalTo(200));
+ }
+
+ // Replace the empty listener by a blocking listener in test
+ final CountDownLatch latch = new CountDownLatch(1);
+ listener = new LatchedActionListener<>(listener, latch);
+
+ // tag::ccr-pause-follow-execute-async
+ client.ccr()
+ .pauseFollowAsync(request, RequestOptions.DEFAULT, listener); // <1>
+ // end::ccr-pause-follow-execute-async
+
+ assertTrue(latch.await(30L, TimeUnit.SECONDS));
+ }
+
+ 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/pause_follow.asciidoc b/docs/java-rest/high-level/ccr/pause_follow.asciidoc
new file mode 100644
index 0000000000000..08acf7cadce8a
--- /dev/null
+++ b/docs/java-rest/high-level/ccr/pause_follow.asciidoc
@@ -0,0 +1,35 @@
+--
+:api: ccr-pause-follow
+:request: PauseFollowRequest
+:response: PauseFollowResponse
+--
+
+[id="{upid}-{api}"]
+=== Pause Follow API
+
+
+[id="{upid}-{api}-request"]
+==== Request
+
+The Pause Follow API allows you to pause following by follow index name.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-request]
+--------------------------------------------------
+<1> The name of follow index.
+
+[id="{upid}-{api}-response"]
+==== Response
+
+The returned +{response}+ indicates if the pause follow request was received.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-response]
+--------------------------------------------------
+<1> Whether or not the pause follow was acknowledge.
+
+include::../execution.asciidoc[]
+
+
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index fb4270566f023..dd867d4691a81 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -397,3 +397,14 @@ don't leak into the rest of the documentation.
:doc-tests-file!:
:upid!:
--
+
+== CCR APIs
+
+:upid: {mainid}-ccr
+:doc-tests-file: {doc-tests}/CCRDocumentationIT.java
+
+The Java High Level REST Client supports the following CCR APIs:
+
+* <<{upid}-ccr-pause-follow>>
+
+include::ccr/pause_follow.asciidoc[]