diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java
index 5e99975f514..14fbf3e1f6d 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterClient.java
@@ -26,6 +26,8 @@ import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest
import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsResponse;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
+import org.elasticsearch.client.cluster.RemoteInfoRequest;
+import org.elasticsearch.client.cluster.RemoteInfoResponse;
import org.elasticsearch.rest.RestStatus;
import java.io.IOException;
@@ -138,4 +140,33 @@ public final class ClusterClient {
return restHighLevelClient.performRequestAsyncAndParseEntity(healthRequest, ClusterRequestConverters::clusterHealth, options,
ClusterHealthResponse::fromXContent, listener, singleton(RestStatus.REQUEST_TIMEOUT.getStatus()));
}
+
+ /**
+ * Get the remote cluster information using the Remote cluster info API.
+ * See Remote cluster info
+ * API on elastic.co
+ * @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 RemoteInfoResponse remoteInfo(RemoteInfoRequest request, RequestOptions options) throws IOException {
+ return restHighLevelClient.performRequestAndParseEntity(request, ClusterRequestConverters::remoteInfo, options,
+ RemoteInfoResponse::fromXContent, singleton(RestStatus.REQUEST_TIMEOUT.getStatus()));
+ }
+
+ /**
+ * Asynchronously get remote cluster information using the Remote cluster info API.
+ * See Remote cluster info
+ * API on elastic.co
+ * @param request the request
+ * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
+ * @param listener the listener to be notified upon request completion
+ * @return cancellable that may be used to cancel the request
+ */
+ public Cancellable remoteInfoAsync(RemoteInfoRequest request, RequestOptions options,
+ ActionListener listener) {
+ return restHighLevelClient.performRequestAsyncAndParseEntity(request, ClusterRequestConverters::remoteInfo, options,
+ RemoteInfoResponse::fromXContent, listener, singleton(RestStatus.REQUEST_TIMEOUT.getStatus()));
+ }
}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterRequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterRequestConverters.java
index a246402b505..74b2c3b7c6a 100644
--- a/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterRequestConverters.java
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/ClusterRequestConverters.java
@@ -25,6 +25,7 @@ import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.support.ActiveShardCount;
+import org.elasticsearch.client.cluster.RemoteInfoRequest;
import org.elasticsearch.common.Strings;
import java.io.IOException;
@@ -76,4 +77,8 @@ final class ClusterRequestConverters {
request.addParameters(params.asMap());
return request;
}
+
+ static Request remoteInfo(RemoteInfoRequest remoteInfoRequest) {
+ return new Request(HttpGet.METHOD_NAME, "/_remote/info");
+ }
}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/ProxyModeInfo.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/ProxyModeInfo.java
new file mode 100644
index 00000000000..0fc4f240eb8
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/ProxyModeInfo.java
@@ -0,0 +1,75 @@
+/*
+ * 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.cluster;
+
+import java.util.Objects;
+
+public class ProxyModeInfo implements RemoteConnectionInfo.ModeInfo {
+ static final String NAME = "proxy";
+ static final String ADDRESS = "address";
+ static final String NUM_SOCKETS_CONNECTED = "num_sockets_connected";
+ static final String MAX_SOCKET_CONNECTIONS = "max_socket_connections";
+ private final String address;
+ private final int maxSocketConnections;
+ private final int numSocketsConnected;
+
+ ProxyModeInfo(String address, int maxSocketConnections, int numSocketsConnected) {
+ this.address = address;
+ this.maxSocketConnections = maxSocketConnections;
+ this.numSocketsConnected = numSocketsConnected;
+ }
+
+ @Override
+ public boolean isConnected() {
+ return numSocketsConnected > 0;
+ }
+
+ @Override
+ public String modeName() {
+ return NAME;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public int getMaxSocketConnections() {
+ return maxSocketConnections;
+ }
+
+ public int getNumSocketsConnected() {
+ return numSocketsConnected;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ProxyModeInfo otherProxy = (ProxyModeInfo) o;
+ return maxSocketConnections == otherProxy.maxSocketConnections &&
+ numSocketsConnected == otherProxy.numSocketsConnected &&
+ Objects.equals(address, otherProxy.address);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(address, maxSocketConnections, numSocketsConnected);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteConnectionInfo.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteConnectionInfo.java
new file mode 100644
index 00000000000..2bf99c61085
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteConnectionInfo.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.cluster;
+
+import org.elasticsearch.common.ParseField;
+import org.elasticsearch.common.xcontent.ConstructingObjectParser;
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+
+import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
+import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
+
+/**
+ * This class encapsulates all remote cluster information to be rendered on
+ * {@code _remote/info} requests.
+ */
+public final class RemoteConnectionInfo {
+ private static final String CONNECTED = "connected";
+ private static final String MODE = "mode";
+ private static final String INITIAL_CONNECT_TIMEOUT = "initial_connect_timeout";
+ private static final String SKIP_UNAVAILABLE = "skip_unavailable";
+
+ @SuppressWarnings("unchecked")
+ private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(
+ "RemoteConnectionInfoObjectParser",
+ false,
+ (args, clusterAlias) -> {
+ String mode = (String) args[1];
+ ModeInfo modeInfo;
+ if (mode.equals(ProxyModeInfo.NAME)) {
+ modeInfo = new ProxyModeInfo((String) args[4], (int) args[5], (int) args[6]);
+ } else if (mode.equals(SniffModeInfo.NAME)) {
+ modeInfo = new SniffModeInfo((List) args[7], (int) args[8], (int) args[9]);
+ } else {
+ throw new IllegalArgumentException("mode cannot be " + mode);
+ }
+ return new RemoteConnectionInfo(clusterAlias,
+ modeInfo,
+ (String) args[2],
+ (boolean) args[3]);
+ });
+
+ static {
+ PARSER.declareBoolean(constructorArg(), new ParseField(CONNECTED));
+ PARSER.declareString(constructorArg(), new ParseField(MODE));
+ PARSER.declareString(constructorArg(), new ParseField(INITIAL_CONNECT_TIMEOUT));
+ PARSER.declareBoolean(constructorArg(), new ParseField(SKIP_UNAVAILABLE));
+
+ PARSER.declareString(optionalConstructorArg(), new ParseField(ProxyModeInfo.ADDRESS));
+ PARSER.declareInt(optionalConstructorArg(), new ParseField(ProxyModeInfo.MAX_SOCKET_CONNECTIONS));
+ PARSER.declareInt(optionalConstructorArg(), new ParseField(ProxyModeInfo.NUM_SOCKETS_CONNECTED));
+
+ PARSER.declareStringArray(optionalConstructorArg(), new ParseField(SniffModeInfo.SEEDS));
+ PARSER.declareInt(optionalConstructorArg(), new ParseField(SniffModeInfo.MAX_CONNECTIONS_PER_CLUSTER));
+ PARSER.declareInt(optionalConstructorArg(), new ParseField(SniffModeInfo.NUM_NODES_CONNECTED));
+ }
+
+ private final ModeInfo modeInfo;
+ // TODO: deprecate and remove this field in favor of initialConnectionTimeout field that is of type TimeValue.
+ // When rest api versioning exists then change org.elasticsearch.transport.RemoteConnectionInfo to properly serialize
+ // the initialConnectionTimeout field so that we can properly parse initialConnectionTimeout as TimeValue
+ private final String initialConnectionTimeoutString;
+ private final String clusterAlias;
+ private final boolean skipUnavailable;
+
+ RemoteConnectionInfo(String clusterAlias, ModeInfo modeInfo, String initialConnectionTimeoutString, boolean skipUnavailable) {
+ this.clusterAlias = clusterAlias;
+ this.modeInfo = modeInfo;
+ this.initialConnectionTimeoutString = initialConnectionTimeoutString;
+ this.skipUnavailable = skipUnavailable;
+ }
+
+ public boolean isConnected() {
+ return modeInfo.isConnected();
+ }
+
+ public String getClusterAlias() {
+ return clusterAlias;
+ }
+
+ public ModeInfo getModeInfo() {
+ return modeInfo;
+ }
+
+ public String getInitialConnectionTimeoutString() {
+ return initialConnectionTimeoutString;
+ }
+
+ public boolean isSkipUnavailable() {
+ return skipUnavailable;
+ }
+
+ public static RemoteConnectionInfo fromXContent(XContentParser parser, String clusterAlias) throws IOException {
+ return PARSER.parse(parser, clusterAlias);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ RemoteConnectionInfo that = (RemoteConnectionInfo) o;
+ return skipUnavailable == that.skipUnavailable &&
+ Objects.equals(modeInfo, that.modeInfo) &&
+ Objects.equals(initialConnectionTimeoutString, that.initialConnectionTimeoutString) &&
+ Objects.equals(clusterAlias, that.clusterAlias);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(modeInfo, initialConnectionTimeoutString, clusterAlias, skipUnavailable);
+ }
+
+ public interface ModeInfo {
+
+ boolean isConnected();
+
+ String modeName();
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteInfoRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteInfoRequest.java
new file mode 100644
index 00000000000..5ffc8afc073
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteInfoRequest.java
@@ -0,0 +1,28 @@
+/*
+ * 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.cluster;
+
+import org.elasticsearch.client.Validatable;
+
+/**
+ * The request object used by the Remote cluster info API.
+ */
+public final class RemoteInfoRequest implements Validatable {
+
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteInfoResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteInfoResponse.java
new file mode 100644
index 00000000000..a0a6f39794a
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/RemoteInfoResponse.java
@@ -0,0 +1,59 @@
+/*
+ * 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.cluster;
+
+import org.elasticsearch.common.xcontent.XContentParser;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
+
+/**
+ * A response to _remote/info API request.
+ */
+public final class RemoteInfoResponse {
+
+ private List infos;
+
+ RemoteInfoResponse(List infos) {
+ this.infos = Collections.unmodifiableList(infos);
+ }
+
+ public List getInfos() {
+ return infos;
+ }
+
+ public static RemoteInfoResponse fromXContent(XContentParser parser) throws IOException {
+ ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser::getTokenLocation);
+
+ List infos = new ArrayList<>();
+
+ XContentParser.Token token;
+ while ((token = parser.nextToken()) == XContentParser.Token.FIELD_NAME) {
+ String clusterAlias = parser.currentName();
+ RemoteConnectionInfo info = RemoteConnectionInfo.fromXContent(parser, clusterAlias);
+ infos.add(info);
+ }
+ ensureExpectedToken(XContentParser.Token.END_OBJECT, token, parser::getTokenLocation);
+ return new RemoteInfoResponse(infos);
+ }
+}
diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/SniffModeInfo.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/SniffModeInfo.java
new file mode 100644
index 00000000000..b0e75979975
--- /dev/null
+++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/cluster/SniffModeInfo.java
@@ -0,0 +1,76 @@
+/*
+ * 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.cluster;
+
+import java.util.List;
+import java.util.Objects;
+
+public class SniffModeInfo implements RemoteConnectionInfo.ModeInfo {
+ public static final String NAME = "sniff";
+ static final String SEEDS = "seeds";
+ static final String NUM_NODES_CONNECTED = "num_nodes_connected";
+ static final String MAX_CONNECTIONS_PER_CLUSTER = "max_connections_per_cluster";
+ final List seedNodes;
+ final int maxConnectionsPerCluster;
+ final int numNodesConnected;
+
+ SniffModeInfo(List seedNodes, int maxConnectionsPerCluster, int numNodesConnected) {
+ this.seedNodes = seedNodes;
+ this.maxConnectionsPerCluster = maxConnectionsPerCluster;
+ this.numNodesConnected = numNodesConnected;
+ }
+
+ @Override
+ public boolean isConnected() {
+ return numNodesConnected > 0;
+ }
+
+ @Override
+ public String modeName() {
+ return NAME;
+ }
+
+ public List getSeedNodes() {
+ return seedNodes;
+ }
+
+ public int getMaxConnectionsPerCluster() {
+ return maxConnectionsPerCluster;
+ }
+
+ public int getNumNodesConnected() {
+ return numNodesConnected;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SniffModeInfo sniff = (SniffModeInfo) o;
+ return maxConnectionsPerCluster == sniff.maxConnectionsPerCluster &&
+ numNodesConnected == sniff.numNodesConnected &&
+ Objects.equals(seedNodes, sniff.seedNodes);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(seedNodes, maxConnectionsPerCluster, numNodesConnected);
+ }
+}
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 11650ca0406..af336061fa7 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
@@ -19,10 +19,7 @@
package org.elasticsearch.client;
-import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.message.ParameterizedMessage;
-import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
-import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
@@ -51,9 +48,7 @@ import org.elasticsearch.client.core.BroadcastResponse;
import org.elasticsearch.client.indices.CloseIndexRequest;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
-import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType;
-import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.seqno.ReplicationTracker;
import org.elasticsearch.test.rest.yaml.ObjectPath;
import org.junit.Before;
@@ -74,27 +69,7 @@ public class CCRIT extends ESRestHighLevelClientTestCase {
@Before
public void setupRemoteClusterConfig() throws Exception {
- // 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_cluster.seeds", transportAddress));
- ClusterUpdateSettingsResponse updateSettingsResponse =
- highLevelClient().cluster().putSettings(updateSettingsRequest, RequestOptions.DEFAULT);
- assertThat(updateSettingsResponse.isAcknowledged(), is(true));
-
- assertBusy(() -> {
- Map, ?> localConnection = (Map, ?>) toMap(client()
- .performRequest(new Request("GET", "/_remote/info")))
- .get("local_cluster");
- assertThat(localConnection, notNullValue());
- assertThat(localConnection.get("connected"), is(true));
- });
+ setupRemoteClusterConfig("local_cluster");
}
public void testIndexFollowing() throws Exception {
@@ -311,8 +286,4 @@ public class CCRIT extends ESRestHighLevelClientTestCase {
assertThat(pauseFollowResponse.isAcknowledged(), is(true));
}
- private static Map toMap(Response response) throws IOException {
- return XContentHelper.convertToMap(JsonXContent.jsonXContent, EntityUtils.toString(response.getEntity()), false);
- }
-
}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterClientIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterClientIT.java
index e78e7ec7ca6..09c8549d725 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterClientIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterClientIT.java
@@ -27,19 +27,27 @@ import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest
import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsResponse;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
+import org.elasticsearch.client.cluster.RemoteConnectionInfo;
+import org.elasticsearch.client.cluster.RemoteInfoRequest;
+import org.elasticsearch.client.cluster.RemoteInfoResponse;
+import org.elasticsearch.client.cluster.SniffModeInfo;
import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.cluster.health.ClusterIndexHealth;
import org.elasticsearch.cluster.health.ClusterShardHealth;
import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.ByteSizeUnit;
+import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
import org.elasticsearch.indices.recovery.RecoverySettings;
import org.elasticsearch.rest.RestStatus;
+import org.elasticsearch.transport.RemoteClusterService;
+import org.elasticsearch.transport.SniffConnectionStrategy;
import java.io.IOException;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import static java.util.Collections.emptyMap;
@@ -297,4 +305,41 @@ public class ClusterClientIT extends ESRestHighLevelClientTestCase {
assertNoIndices(response);
}
+ public void testRemoteInfo() throws Exception {
+ String clusterAlias = "local_cluster";
+ setupRemoteClusterConfig(clusterAlias);
+
+ ClusterGetSettingsRequest settingsRequest = new ClusterGetSettingsRequest();
+ settingsRequest.includeDefaults(true);
+ ClusterGetSettingsResponse settingsResponse = highLevelClient().cluster().getSettings(settingsRequest, RequestOptions.DEFAULT);
+
+ List seeds = SniffConnectionStrategy.REMOTE_CLUSTER_SEEDS
+ .getConcreteSettingForNamespace(clusterAlias)
+ .get(settingsResponse.getTransientSettings());
+ int connectionsPerCluster = SniffConnectionStrategy.REMOTE_CONNECTIONS_PER_CLUSTER
+ .get(settingsResponse.getTransientSettings());
+ TimeValue initialConnectionTimeout = RemoteClusterService.REMOTE_INITIAL_CONNECTION_TIMEOUT_SETTING
+ .get(settingsResponse.getTransientSettings());
+ boolean skipUnavailable = RemoteClusterService.REMOTE_CLUSTER_SKIP_UNAVAILABLE
+ .getConcreteSettingForNamespace(clusterAlias)
+ .get(settingsResponse.getTransientSettings());
+
+ RemoteInfoRequest request = new RemoteInfoRequest();
+ RemoteInfoResponse response = execute(request, highLevelClient().cluster()::remoteInfo,
+ highLevelClient().cluster()::remoteInfoAsync);
+
+ assertThat(response, notNullValue());
+ assertThat(response.getInfos().size(), equalTo(1));
+ RemoteConnectionInfo info = response.getInfos().get(0);
+ assertThat(info.getClusterAlias(), equalTo(clusterAlias));
+ assertThat(info.getInitialConnectionTimeoutString(), equalTo(initialConnectionTimeout.toString()));
+ assertThat(info.isSkipUnavailable(), equalTo(skipUnavailable));
+ assertThat(info.getModeInfo().modeName(), equalTo(SniffModeInfo.NAME));
+ assertThat(info.getModeInfo().isConnected(), equalTo(true));
+ SniffModeInfo sniffModeInfo = (SniffModeInfo) info.getModeInfo();
+ assertThat(sniffModeInfo.getMaxConnectionsPerCluster(), equalTo(connectionsPerCluster));
+ assertThat(sniffModeInfo.getNumNodesConnected(), equalTo(1));
+ assertThat(sniffModeInfo.getSeedNodes(), equalTo(seeds));
+ }
+
}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterRequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterRequestConvertersTests.java
index 9b7b5b0d284..59bf52a6773 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterRequestConvertersTests.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ClusterRequestConvertersTests.java
@@ -26,6 +26,7 @@ import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
+import org.elasticsearch.client.cluster.RemoteInfoRequest;
import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.common.Priority;
import org.elasticsearch.test.ESTestCase;
@@ -37,6 +38,7 @@ import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
+import static java.util.Collections.emptyMap;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.nullValue;
@@ -147,4 +149,12 @@ public class ClusterRequestConvertersTests extends ESTestCase {
}
Assert.assertThat(request.getParameters(), equalTo(expectedParams));
}
+
+ public void testRemoteInfo() {
+ RemoteInfoRequest request = new RemoteInfoRequest();
+ Request expectedRequest = ClusterRequestConverters.remoteInfo(request);
+ assertEquals("/_remote/info", expectedRequest.getEndpoint());
+ assertEquals(HttpGet.METHOD_NAME, expectedRequest.getMethod());
+ assertEquals(emptyMap(), expectedRequest.getParameters());
+ }
}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java
index b54e4f2434e..8967bae1d7f 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/ESRestHighLevelClientTestCase.java
@@ -19,19 +19,25 @@
package org.elasticsearch.client;
+import org.apache.http.util.EntityUtils;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
+import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
import org.elasticsearch.action.ingest.PutPipelineRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.PlainActionFuture;
+import org.elasticsearch.client.cluster.RemoteInfoRequest;
+import org.elasticsearch.client.cluster.RemoteInfoResponse;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.common.Booleans;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
import org.elasticsearch.common.xcontent.XContentBuilder;
+import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.core.internal.io.IOUtils;
import org.elasticsearch.ingest.Pipeline;
import org.elasticsearch.search.SearchHit;
@@ -45,10 +51,15 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
+import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
+import static java.util.Collections.singletonMap;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
public abstract class ESRestHighLevelClientTestCase extends ESRestTestCase {
@@ -243,4 +254,30 @@ public abstract class ESRestHighLevelClientTestCase extends ESRestTestCase {
);
highLevelClient().indices().create(indexRequest, RequestOptions.DEFAULT);
}
+
+ protected static void setupRemoteClusterConfig(String remoteClusterName) throws Exception {
+ // 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(singletonMap("cluster.remote." + remoteClusterName + ".seeds", transportAddress));
+ ClusterUpdateSettingsResponse updateSettingsResponse =
+ restHighLevelClient.cluster().putSettings(updateSettingsRequest, RequestOptions.DEFAULT);
+ assertThat(updateSettingsResponse.isAcknowledged(), is(true));
+
+ assertBusy(() -> {
+ RemoteInfoResponse response = highLevelClient().cluster().remoteInfo(new RemoteInfoRequest(), RequestOptions.DEFAULT);
+ assertThat(response, notNullValue());
+ assertThat(response.getInfos().size(), greaterThan(0));
+ });
+ }
+
+ protected static Map toMap(Response response) throws IOException {
+ return XContentHelper.convertToMap(JsonXContent.jsonXContent, EntityUtils.toString(response.getEntity()), false);
+ }
}
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 f1d9976cd60..552c88d3ab8 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
@@ -59,8 +59,8 @@ import org.elasticsearch.client.ml.dataframe.DataFrameAnalysis;
import org.elasticsearch.client.ml.dataframe.OutlierDetection;
import org.elasticsearch.client.ml.dataframe.evaluation.classification.AccuracyMetric;
import org.elasticsearch.client.ml.dataframe.evaluation.classification.Classification;
-import org.elasticsearch.client.ml.dataframe.evaluation.regression.MeanSquaredErrorMetric;
import org.elasticsearch.client.ml.dataframe.evaluation.classification.MulticlassConfusionMatrixMetric;
+import org.elasticsearch.client.ml.dataframe.evaluation.regression.MeanSquaredErrorMetric;
import org.elasticsearch.client.ml.dataframe.evaluation.regression.RSquaredMetric;
import org.elasticsearch.client.ml.dataframe.evaluation.regression.Regression;
import org.elasticsearch.client.ml.dataframe.evaluation.softclassification.AucRocMetric;
@@ -68,14 +68,14 @@ import org.elasticsearch.client.ml.dataframe.evaluation.softclassification.Binar
import org.elasticsearch.client.ml.dataframe.evaluation.softclassification.ConfusionMatrixMetric;
import org.elasticsearch.client.ml.dataframe.evaluation.softclassification.PrecisionMetric;
import org.elasticsearch.client.ml.dataframe.evaluation.softclassification.RecallMetric;
+import org.elasticsearch.client.ml.inference.preprocessing.FrequencyEncoding;
+import org.elasticsearch.client.ml.inference.preprocessing.OneHotEncoding;
+import org.elasticsearch.client.ml.inference.preprocessing.TargetMeanEncoding;
import org.elasticsearch.client.ml.inference.trainedmodel.ensemble.Ensemble;
import org.elasticsearch.client.ml.inference.trainedmodel.ensemble.LogisticRegression;
import org.elasticsearch.client.ml.inference.trainedmodel.ensemble.WeightedMode;
import org.elasticsearch.client.ml.inference.trainedmodel.ensemble.WeightedSum;
import org.elasticsearch.client.ml.inference.trainedmodel.tree.Tree;
-import org.elasticsearch.client.ml.inference.preprocessing.FrequencyEncoding;
-import org.elasticsearch.client.ml.inference.preprocessing.OneHotEncoding;
-import org.elasticsearch.client.ml.inference.preprocessing.TargetMeanEncoding;
import org.elasticsearch.client.transform.transforms.SyncConfig;
import org.elasticsearch.client.transform.transforms.TimeSyncConfig;
import org.elasticsearch.common.CheckedFunction;
@@ -106,7 +106,6 @@ import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.InternalAggregationTestCase;
import org.elasticsearch.test.rest.yaml.restspec.ClientYamlSuiteRestApi;
import org.elasticsearch.test.rest.yaml.restspec.ClientYamlSuiteRestSpec;
-
import org.hamcrest.Matchers;
import org.junit.Before;
@@ -773,7 +772,6 @@ public class RestHighLevelClientTests extends ESTestCase {
public void testApiNamingConventions() throws Exception {
//this list should be empty once the high-level client is feature complete
String[] notYetSupportedApi = new String[]{
- "cluster.remote_info",
"create",
"get_script_context",
"get_script_languages",
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/cluster/RemoteInfoResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/cluster/RemoteInfoResponseTests.java
new file mode 100644
index 00000000000..88f8f6f533e
--- /dev/null
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/cluster/RemoteInfoResponseTests.java
@@ -0,0 +1,112 @@
+/*
+ * 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.cluster;
+
+import org.elasticsearch.client.AbstractResponseTestCase;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.common.xcontent.XContentParser;
+import org.elasticsearch.common.xcontent.XContentType;
+import org.elasticsearch.transport.ProxyConnectionStrategy;
+import org.elasticsearch.transport.RemoteConnectionInfo;
+import org.elasticsearch.transport.SniffConnectionStrategy;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import static java.util.function.Function.identity;
+import static java.util.stream.Collectors.toMap;
+import static org.hamcrest.Matchers.equalTo;
+
+public class RemoteInfoResponseTests extends AbstractResponseTestCase {
+
+ @Override
+ protected org.elasticsearch.action.admin.cluster.remote.RemoteInfoResponse createServerTestInstance(XContentType xContentType) {
+ int numRemoteInfos = randomIntBetween(0, 8);
+ List remoteInfos = new ArrayList<>();
+ for (int i = 0; i < numRemoteInfos; i++) {
+ remoteInfos.add(createRandomRemoteConnectionInfo());
+ }
+ return new org.elasticsearch.action.admin.cluster.remote.RemoteInfoResponse(remoteInfos);
+ }
+
+ @Override
+ protected RemoteInfoResponse doParseToClientInstance(XContentParser parser) throws IOException {
+ return RemoteInfoResponse.fromXContent(parser);
+ }
+
+ @Override
+ protected void assertInstances(org.elasticsearch.action.admin.cluster.remote.RemoteInfoResponse serverTestInstance,
+ RemoteInfoResponse clientInstance) {
+ assertThat(clientInstance.getInfos().size(), equalTo(serverTestInstance.getInfos().size()));
+ Map serverInfos = serverTestInstance.getInfos().stream()
+ .collect(toMap(RemoteConnectionInfo::getClusterAlias, identity()));
+ for (org.elasticsearch.client.cluster.RemoteConnectionInfo clientRemoteInfo : clientInstance.getInfos()) {
+ RemoteConnectionInfo serverRemoteInfo = serverInfos.get(clientRemoteInfo.getClusterAlias());
+ assertThat(clientRemoteInfo.getClusterAlias(), equalTo(serverRemoteInfo.getClusterAlias()));
+ assertThat(clientRemoteInfo.getInitialConnectionTimeoutString(),
+ equalTo(serverRemoteInfo.getInitialConnectionTimeout().toString()));
+ assertThat(clientRemoteInfo.isConnected(), equalTo(serverRemoteInfo.isConnected()));
+ assertThat(clientRemoteInfo.isSkipUnavailable(), equalTo(serverRemoteInfo.isSkipUnavailable()));
+ assertThat(clientRemoteInfo.getModeInfo().isConnected(), equalTo(serverRemoteInfo.getModeInfo().isConnected()));
+ assertThat(clientRemoteInfo.getModeInfo().modeName(), equalTo(serverRemoteInfo.getModeInfo().modeName()));
+ if (clientRemoteInfo.getModeInfo().modeName().equals(SniffModeInfo.NAME)) {
+ SniffModeInfo clientModeInfo =
+ (SniffModeInfo) clientRemoteInfo.getModeInfo();
+ SniffConnectionStrategy.SniffModeInfo serverModeInfo =
+ (SniffConnectionStrategy.SniffModeInfo) serverRemoteInfo.getModeInfo();
+ assertThat(clientModeInfo.getMaxConnectionsPerCluster(), equalTo(serverModeInfo.getMaxConnectionsPerCluster()));
+ assertThat(clientModeInfo.getNumNodesConnected(), equalTo(serverModeInfo.getNumNodesConnected()));
+ assertThat(clientModeInfo.getSeedNodes(), equalTo(serverModeInfo.getSeedNodes()));
+ } else if (clientRemoteInfo.getModeInfo().modeName().equals(ProxyModeInfo.NAME)) {
+ ProxyModeInfo clientModeInfo =
+ (ProxyModeInfo) clientRemoteInfo.getModeInfo();
+ ProxyConnectionStrategy.ProxyModeInfo serverModeInfo =
+ (ProxyConnectionStrategy.ProxyModeInfo) serverRemoteInfo.getModeInfo();
+ assertThat(clientModeInfo.getAddress(), equalTo(serverModeInfo.getAddress()));
+ assertThat(clientModeInfo.getMaxSocketConnections(), equalTo(serverModeInfo.getMaxSocketConnections()));
+ assertThat(clientModeInfo.getNumSocketsConnected(), equalTo(serverModeInfo.getNumSocketsConnected()));
+ } else {
+ fail("impossible case");
+ }
+ }
+ }
+
+ private static RemoteConnectionInfo createRandomRemoteConnectionInfo() {
+ RemoteConnectionInfo.ModeInfo modeInfo;
+ if (randomBoolean()) {
+ String address = randomAlphaOfLength(8);
+ int maxSocketConnections = randomInt(5);
+ int numSocketsConnected = randomInt(5);
+ modeInfo = new ProxyConnectionStrategy.ProxyModeInfo(address, maxSocketConnections, numSocketsConnected);
+ } else {
+ List seedNodes = randomList(randomInt(8), () -> randomAlphaOfLength(8));
+ int maxConnectionsPerCluster = randomInt(5);
+ int numNodesConnected = randomInt(5);
+ modeInfo = new SniffConnectionStrategy.SniffModeInfo(seedNodes, maxConnectionsPerCluster, numNodesConnected);
+ }
+ String clusterAlias = randomAlphaOfLength(8);
+ TimeValue initialConnectionTimeout = TimeValue.parseTimeValue(randomTimeValue(), "randomInitialConnectionTimeout");
+ boolean skipUnavailable = randomBoolean();
+ return new RemoteConnectionInfo(clusterAlias, modeInfo, initialConnectionTimeout, skipUnavailable);
+ }
+}
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 8595675792b..643a8d93b45 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
@@ -19,11 +19,8 @@
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.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
@@ -57,8 +54,6 @@ import org.elasticsearch.client.core.BroadcastResponse;
import org.elasticsearch.client.indices.CloseIndexRequest;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
-import org.elasticsearch.common.xcontent.XContentHelper;
-import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.test.rest.yaml.ObjectPath;
import org.junit.Before;
@@ -76,21 +71,8 @@ import static org.hamcrest.Matchers.is;
public class CCRDocumentationIT extends ESRestHighLevelClientTestCase {
@Before
- public void setupRemoteClusterConfig() throws IOException {
- 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));
+ public void setupRemoteClusterConfig() throws Exception {
+ setupRemoteClusterConfig("local");
}
public void testPutFollow() throws Exception {
@@ -987,8 +969,4 @@ public class CCRDocumentationIT extends ESRestHighLevelClientTestCase {
}
}
- static Map toMap(Response response) throws IOException {
- return XContentHelper.convertToMap(JsonXContent.jsonXContent, EntityUtils.toString(response.getEntity()), false);
- }
-
}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ClusterClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ClusterClientDocumentationIT.java
index 8b7f1577114..449b35acc06 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ClusterClientDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ClusterClientDocumentationIT.java
@@ -31,6 +31,9 @@ import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.client.cluster.RemoteConnectionInfo;
+import org.elasticsearch.client.cluster.RemoteInfoRequest;
+import org.elasticsearch.client.cluster.RemoteInfoResponse;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.cluster.health.ClusterIndexHealth;
@@ -46,6 +49,7 @@ import org.elasticsearch.rest.RestStatus;
import java.io.IOException;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -415,4 +419,60 @@ public class ClusterClientDocumentationIT extends ESRestHighLevelClientTestCase
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
}
+
+ public void testRemoteInfo() throws Exception {
+ setupRemoteClusterConfig("local_cluster");
+
+ RestHighLevelClient client = highLevelClient();
+
+ // tag::remote-info-request
+ RemoteInfoRequest request = new RemoteInfoRequest();
+ // end::remote-info-request
+
+ // tag::remote-info-execute
+ RemoteInfoResponse response = client.cluster().remoteInfo(request, RequestOptions.DEFAULT); // <1>
+ // end::remote-info-execute
+
+ // tag::remote-info-response
+ List infos = response.getInfos();
+ // end::remote-info-response
+
+ assertThat(infos.size(), greaterThan(0));
+ }
+
+ public void testRemoteInfoAsync() throws Exception {
+ setupRemoteClusterConfig("local_cluster");
+
+ RestHighLevelClient client = highLevelClient();
+
+ // tag::remote-info-request
+ RemoteInfoRequest request = new RemoteInfoRequest();
+ // end::remote-info-request
+
+
+ // tag::remote-info-execute-listener
+ ActionListener listener =
+ new ActionListener() {
+ @Override
+ public void onResponse(RemoteInfoResponse response) {
+ // <1>
+ }
+
+ @Override
+ public void onFailure(Exception e) {
+ // <2>
+ }
+ };
+ // end::remote-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::health-execute-async
+ client.cluster().remoteInfoAsync(request, RequestOptions.DEFAULT, listener); // <1>
+ // end::health-execute-async
+
+ assertTrue(latch.await(30L, TimeUnit.SECONDS));
+ }
}
diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ILMDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ILMDocumentationIT.java
index 9ff5d0936cc..887fb510bca 100644
--- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ILMDocumentationIT.java
+++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/ILMDocumentationIT.java
@@ -19,7 +19,6 @@
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.repositories.put.PutRepositoryRequest;
@@ -28,7 +27,6 @@ import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.RequestOptions;
-import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.core.AcknowledgedResponse;
import org.elasticsearch.client.indexlifecycle.DeleteAction;
@@ -78,8 +76,6 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
-import org.elasticsearch.common.xcontent.XContentHelper;
-import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.repositories.fs.FsRepository;
import org.elasticsearch.snapshots.SnapshotInfo;
import org.elasticsearch.snapshots.SnapshotState;
@@ -1210,8 +1206,4 @@ public class ILMDocumentationIT extends ESRestHighLevelClientTestCase {
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/cluster/remote_info.asciidoc b/docs/java-rest/high-level/cluster/remote_info.asciidoc
new file mode 100644
index 00000000000..6496a04a3a7
--- /dev/null
+++ b/docs/java-rest/high-level/cluster/remote_info.asciidoc
@@ -0,0 +1,32 @@
+--
+:api: remote-info
+:request: RemoteInfoRequest
+:response: RemoteInfoResponse
+--
+
+[id="{upid}-{api}"]
+=== Remote Cluster Info API
+
+The Remote cluster info API allows to get all of the configured remote cluster information.
+
+[id="{upid}-{api}-request"]
+==== Remote Cluster Info Request
+
+A +{request}+:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-request]
+--------------------------------------------------
+
+There are no required parameters.
+
+==== Remote Cluster Info Response
+
+The returned +{response}+ allows to retrieve remote cluster information.
+It returns connection and endpoint information keyed by the configured remote cluster alias.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests-file}[{api}-response]
+--------------------------------------------------
diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc
index 2191e795ebb..e0d228b5d1e 100644
--- a/docs/java-rest/high-level/supported-apis.asciidoc
+++ b/docs/java-rest/high-level/supported-apis.asciidoc
@@ -168,12 +168,14 @@ The Java High Level REST Client supports the following Cluster APIs:
* <>
* <>
* <>
+* <>
:upid: {mainid}-cluster
:doc-tests-file: {doc-tests}/ClusterClientDocumentationIT.java
include::cluster/put_settings.asciidoc[]
include::cluster/get_settings.asciidoc[]
include::cluster/health.asciidoc[]
+include::cluster/remote_info.asciidoc[]
== Ingest APIs
The Java High Level REST Client supports the following Ingest APIs:
diff --git a/server/src/main/java/org/elasticsearch/action/admin/cluster/remote/RemoteInfoResponse.java b/server/src/main/java/org/elasticsearch/action/admin/cluster/remote/RemoteInfoResponse.java
index c92a6c19969..a20946308d9 100644
--- a/server/src/main/java/org/elasticsearch/action/admin/cluster/remote/RemoteInfoResponse.java
+++ b/server/src/main/java/org/elasticsearch/action/admin/cluster/remote/RemoteInfoResponse.java
@@ -41,7 +41,7 @@ public final class RemoteInfoResponse extends ActionResponse implements ToXConte
infos = in.readList(RemoteConnectionInfo::new);
}
- RemoteInfoResponse(Collection infos) {
+ public RemoteInfoResponse(Collection infos) {
this.infos = Collections.unmodifiableList(new ArrayList<>(infos));
}
diff --git a/server/src/main/java/org/elasticsearch/transport/ProxyConnectionStrategy.java b/server/src/main/java/org/elasticsearch/transport/ProxyConnectionStrategy.java
index 3bd6e54d2b2..52465e1b638 100644
--- a/server/src/main/java/org/elasticsearch/transport/ProxyConnectionStrategy.java
+++ b/server/src/main/java/org/elasticsearch/transport/ProxyConnectionStrategy.java
@@ -268,13 +268,13 @@ public class ProxyConnectionStrategy extends RemoteConnectionStrategy {
return new TransportAddress(parseConfiguredAddress(address));
}
- static class ProxyModeInfo implements RemoteConnectionInfo.ModeInfo {
+ public static class ProxyModeInfo implements RemoteConnectionInfo.ModeInfo {
private final String address;
private final int maxSocketConnections;
private final int numSocketsConnected;
- ProxyModeInfo(String address, int maxSocketConnections, int numSocketsConnected) {
+ public ProxyModeInfo(String address, int maxSocketConnections, int numSocketsConnected) {
this.address = address;
this.maxSocketConnections = maxSocketConnections;
this.numSocketsConnected = numSocketsConnected;
@@ -311,6 +311,18 @@ public class ProxyConnectionStrategy extends RemoteConnectionStrategy {
return "proxy";
}
+ public String getAddress() {
+ return address;
+ }
+
+ public int getMaxSocketConnections() {
+ return maxSocketConnections;
+ }
+
+ public int getNumSocketsConnected() {
+ return numSocketsConnected;
+ }
+
@Override
public RemoteConnectionStrategy.ConnectionStrategy modeType() {
return RemoteConnectionStrategy.ConnectionStrategy.PROXY;
diff --git a/server/src/main/java/org/elasticsearch/transport/RemoteConnectionInfo.java b/server/src/main/java/org/elasticsearch/transport/RemoteConnectionInfo.java
index a955d30b7b7..814a20ea99a 100644
--- a/server/src/main/java/org/elasticsearch/transport/RemoteConnectionInfo.java
+++ b/server/src/main/java/org/elasticsearch/transport/RemoteConnectionInfo.java
@@ -50,7 +50,7 @@ public final class RemoteConnectionInfo implements ToXContentFragment, Writeable
final String clusterAlias;
final boolean skipUnavailable;
- RemoteConnectionInfo(String clusterAlias, ModeInfo modeInfo, TimeValue initialConnectionTimeout, boolean skipUnavailable) {
+ public RemoteConnectionInfo(String clusterAlias, ModeInfo modeInfo, TimeValue initialConnectionTimeout, boolean skipUnavailable) {
this.clusterAlias = clusterAlias;
this.modeInfo = modeInfo;
this.initialConnectionTimeout = initialConnectionTimeout;
@@ -103,6 +103,18 @@ public final class RemoteConnectionInfo implements ToXContentFragment, Writeable
return clusterAlias;
}
+ public ModeInfo getModeInfo() {
+ return modeInfo;
+ }
+
+ public TimeValue getInitialConnectionTimeout() {
+ return initialConnectionTimeout;
+ }
+
+ public boolean isSkipUnavailable() {
+ return skipUnavailable;
+ }
+
@Override
public void writeTo(StreamOutput out) throws IOException {
if (out.getVersion().onOrAfter(Version.V_7_6_0)) {
diff --git a/server/src/main/java/org/elasticsearch/transport/SniffConnectionStrategy.java b/server/src/main/java/org/elasticsearch/transport/SniffConnectionStrategy.java
index 260ea958829..52c5a1a86ed 100644
--- a/server/src/main/java/org/elasticsearch/transport/SniffConnectionStrategy.java
+++ b/server/src/main/java/org/elasticsearch/transport/SniffConnectionStrategy.java
@@ -534,13 +534,13 @@ public class SniffConnectionStrategy extends RemoteConnectionStrategy {
return Objects.equals(oldProxy, newProxy) == false;
}
- static class SniffModeInfo implements RemoteConnectionInfo.ModeInfo {
+ public static class SniffModeInfo implements RemoteConnectionInfo.ModeInfo {
final List seedNodes;
final int maxConnectionsPerCluster;
final int numNodesConnected;
- SniffModeInfo(List seedNodes, int maxConnectionsPerCluster, int numNodesConnected) {
+ public SniffModeInfo(List seedNodes, int maxConnectionsPerCluster, int numNodesConnected) {
this.seedNodes = seedNodes;
this.maxConnectionsPerCluster = maxConnectionsPerCluster;
this.numNodesConnected = numNodesConnected;
@@ -581,6 +581,18 @@ public class SniffConnectionStrategy extends RemoteConnectionStrategy {
return "sniff";
}
+ public List getSeedNodes() {
+ return seedNodes;
+ }
+
+ public int getMaxConnectionsPerCluster() {
+ return maxConnectionsPerCluster;
+ }
+
+ public int getNumNodesConnected() {
+ return numNodesConnected;
+ }
+
@Override
public RemoteConnectionStrategy.ConnectionStrategy modeType() {
return RemoteConnectionStrategy.ConnectionStrategy.SNIFF;
diff --git a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java
index 43d115fddf9..27d9915fcc9 100644
--- a/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java
+++ b/test/framework/src/main/java/org/elasticsearch/test/ESTestCase.java
@@ -780,6 +780,19 @@ public abstract class ESTestCase extends LuceneTestCase {
return array;
}
+ public static List randomList(int maxListSize, Supplier valueConstructor) {
+ return randomList(0, maxListSize, valueConstructor);
+ }
+
+ public static List randomList(int minListSize, int maxListSize, Supplier valueConstructor) {
+ final int size = randomIntBetween(minListSize, maxListSize);
+ List list = new ArrayList<>();
+ for (int i = 0; i < size; i++) {
+ list.add(valueConstructor.get());
+ }
+ return list;
+ }
+
private static final String[] TIME_SUFFIXES = new String[]{"d", "h", "ms", "s", "m", "micros", "nanos"};