Skip to content

Commit

Permalink
HLRC: Convert xpack methods to client side objects (#40705)
Browse files Browse the repository at this point in the history
This commit fixes a problem with BWC that was brought up in #40511. A
newer version of the code was emitting a new value for an enum to an
older version, and the older version could not handle that. It caused
the response to error. The MainResponse is now relaxed, and will accept
whatever values the server expose, and holds most of them as Strings
instead of complex objects.

Fixes #40511
  • Loading branch information
hub-cap committed Apr 4, 2019
1 parent 9e8499d commit fb5a065
Show file tree
Hide file tree
Showing 10 changed files with 361 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.main.MainRequest;
import org.elasticsearch.action.main.MainResponse;
import org.elasticsearch.action.search.ClearScrollRequest;
import org.elasticsearch.action.search.ClearScrollResponse;
import org.elasticsearch.action.search.MultiSearchRequest;
Expand All @@ -58,6 +56,8 @@
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.client.core.MainRequest;
import org.elasticsearch.client.core.MainResponse;
import org.elasticsearch.client.core.MultiTermVectorsRequest;
import org.elasticsearch.client.core.MultiTermVectorsResponse;
import org.elasticsearch.client.core.TermVectorsRequest;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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.client.Validatable;

public class MainRequest implements Validatable {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/*
* 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.ParseField;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.XContentParser;

import java.util.Objects;

public class MainResponse {

@SuppressWarnings("unchecked")
private static ConstructingObjectParser<MainResponse, Void> PARSER =
new ConstructingObjectParser<>(MainResponse.class.getName(), true,
args -> {
return new MainResponse((String) args[0], (Version) args[1], (String) args[2], (String) args[3], (String) args[4]);
}
);

static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("name"));
PARSER.declareObject(ConstructingObjectParser.constructorArg(), Version.PARSER, new ParseField("version"));
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("cluster_name"));
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("cluster_uuid"));
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("tagline"));

}

private final String nodeName;
private final Version version;
private final String clusterName;
private final String clusterUuid;
private final String tagline;

public MainResponse(String nodeName, Version version, String clusterName, String clusterUuid, String tagline) {
this.nodeName = nodeName;
this.version = version;
this.clusterName = clusterName;
this.clusterUuid = clusterUuid;
this.tagline = tagline;
}

public String getNodeName() {
return nodeName;
}

public Version getVersion() {
return version;
}

public String getClusterName() {
return clusterName;
}

public String getClusterUuid() {
return clusterUuid;
}

public String getTagline() {
return tagline;
}

public static MainResponse fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
MainResponse that = (MainResponse) o;
return nodeName.equals(that.nodeName) &&
version.equals(that.version) &&
clusterName.equals(that.clusterName) &&
clusterUuid.equals(that.clusterUuid) &&
tagline.equals(that.tagline);
}

@Override
public int hashCode() {
return Objects.hash(nodeName, version, clusterName, clusterUuid, tagline);
}

public static class Version {
@SuppressWarnings("unchecked")
private static ConstructingObjectParser<Version, Void> PARSER =
new ConstructingObjectParser<>(Version.class.getName(), true,
args -> {
return new Version((String) args[0], (String) args[1], (String) args[2], (String) args[3], (String) args[4],
(Boolean) args[5], (String) args[6], (String) args[7], (String) args[8]);
}
);

static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("number"));
PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("build_flavor"));
PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("build_type"));
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("build_hash"));
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("build_date"));
PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), new ParseField("build_snapshot"));
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("lucene_version"));
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("minimum_wire_compatibility_version"));
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("minimum_index_compatibility_version"));
}
private final String number;
private final String buildFlavor;
private final String buildType;
private final String buildHash;
private final String buildDate;
private final boolean isSnapshot;
private final String luceneVersion;
private final String minimumWireCompatibilityVersion;
private final String minimumIndexCompatibilityVersion;

public Version(String number, String buildFlavor, String buildType, String buildHash, String buildDate, boolean isSnapshot,
String luceneVersion, String minimumWireCompatibilityVersion, String minimumIndexCompatibilityVersion) {
this.number = number;
this.buildFlavor = buildFlavor;
this.buildType = buildType;
this.buildHash = buildHash;
this.buildDate = buildDate;
this.isSnapshot = isSnapshot;
this.luceneVersion = luceneVersion;
this.minimumWireCompatibilityVersion = minimumWireCompatibilityVersion;
this.minimumIndexCompatibilityVersion = minimumIndexCompatibilityVersion;
}

public String getNumber() {
return number;
}

public String getBuildFlavor() {
return buildFlavor;
}

public String getBuildType() {
return buildType;
}

public String getBuildHash() {
return buildHash;
}

public String getBuildDate() {
return buildDate;
}

public boolean isSnapshot() {
return isSnapshot;
}

public String getLuceneVersion() {
return luceneVersion;
}

public String getMinimumWireCompatibilityVersion() {
return minimumWireCompatibilityVersion;
}

public String getMinimumIndexCompatibilityVersion() {
return minimumIndexCompatibilityVersion;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Version version = (Version) o;
return isSnapshot == version.isSnapshot &&
number.equals(version.number) &&
Objects.equals(buildFlavor, version.buildFlavor) &&
Objects.equals(buildType, version.buildType) &&
buildHash.equals(version.buildHash) &&
buildDate.equals(version.buildDate) &&
luceneVersion.equals(version.luceneVersion) &&
minimumWireCompatibilityVersion.equals(version.minimumWireCompatibilityVersion) &&
minimumIndexCompatibilityVersion.equals(version.minimumIndexCompatibilityVersion);
}

@Override
public int hashCode() {
return Objects.hash(number, buildFlavor, buildType, buildHash, buildDate, isSnapshot, luceneVersion,
minimumWireCompatibilityVersion, minimumIndexCompatibilityVersion);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ public void testForgetFollower() throws IOException {
assertTrue(putFollowResponse.isFollowIndexShardsAcked());
assertTrue(putFollowResponse.isIndexFollowingStarted());

final String clusterName = highLevelClient().info(RequestOptions.DEFAULT).getClusterName().value();
final String clusterName = highLevelClient().info(RequestOptions.DEFAULT).getClusterName();

final Request statsRequest = new Request("GET", "/follower/_stats");
final Response statsResponse = client().performRequest(statsRequest);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
package org.elasticsearch.client;

import org.apache.http.client.methods.HttpGet;
import org.elasticsearch.action.main.MainResponse;
import org.elasticsearch.client.core.MainResponse;
import org.elasticsearch.client.xpack.XPackInfoRequest;
import org.elasticsearch.client.xpack.XPackInfoResponse;
import org.elasticsearch.client.xpack.XPackInfoResponse.FeatureSetsInfo.FeatureSet;
Expand All @@ -40,20 +40,20 @@ public void testInfo() throws IOException {
MainResponse info = highLevelClient().info(RequestOptions.DEFAULT);
// compare with what the low level client outputs
Map<String, Object> infoAsMap = entityAsMap(adminClient().performRequest(new Request(HttpGet.METHOD_NAME, "/")));
assertEquals(infoAsMap.get("cluster_name"), info.getClusterName().value());
assertEquals(infoAsMap.get("cluster_name"), info.getClusterName());
assertEquals(infoAsMap.get("cluster_uuid"), info.getClusterUuid());

// only check node name existence, might be a different one from what was hit by low level client in multi-node cluster
assertNotNull(info.getNodeName());
@SuppressWarnings("unchecked")
Map<String, Object> versionMap = (Map<String, Object>) infoAsMap.get("version");
assertEquals(versionMap.get("build_flavor"), info.getBuild().flavor().displayName());
assertEquals(versionMap.get("build_type"), info.getBuild().type().displayName());
assertEquals(versionMap.get("build_hash"), info.getBuild().shortHash());
assertEquals(versionMap.get("build_date"), info.getBuild().date());
assertEquals(versionMap.get("build_snapshot"), info.getBuild().isSnapshot());
assertTrue(versionMap.get("number").toString().startsWith(info.getVersion().toString()));
assertEquals(versionMap.get("lucene_version"), info.getVersion().luceneVersion.toString());
assertEquals(versionMap.get("build_flavor"), info.getVersion().getBuildFlavor());
assertEquals(versionMap.get("build_type"), info.getVersion().getBuildType());
assertEquals(versionMap.get("build_hash"), info.getVersion().getBuildHash());
assertEquals(versionMap.get("build_date"), info.getVersion().getBuildDate());
assertEquals(versionMap.get("build_snapshot"), info.getVersion().isSnapshot());
assertTrue(versionMap.get("number").toString().startsWith(info.getVersion().getNumber()));
assertEquals(versionMap.get("lucene_version"), info.getVersion().getLuceneVersion());
}

public void testXPackInfo() throws IOException {
Expand All @@ -64,7 +64,7 @@ public void testXPackInfo() throws IOException {

MainResponse mainResponse = highLevelClient().info(RequestOptions.DEFAULT);

assertEquals(mainResponse.getBuild().shortHash(), info.getBuildInfo().getHash());
assertEquals(mainResponse.getVersion().getBuildHash(), info.getBuildInfo().getHash());

assertEquals("trial", info.getLicenseInfo().getType());
assertEquals("trial", info.getLicenseInfo().getMode());
Expand All @@ -84,7 +84,7 @@ public void testXPackInfo() throws IOException {
assertNotNull(ml.description());
assertTrue(ml.available());
assertTrue(ml.enabled());
assertEquals(mainResponse.getBuild().getQualifiedVersion(), ml.nativeCodeInfo().get("version").toString());
assertEquals(mainResponse.getVersion().getNumber(), ml.nativeCodeInfo().get("version").toString());
}

public void testXPackInfoEmptyRequest() throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,18 @@
import org.apache.http.message.BasicStatusLine;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.apache.http.nio.entity.NStringEntity;
import org.elasticsearch.Build;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.main.MainRequest;
import org.elasticsearch.action.main.MainResponse;
import org.elasticsearch.action.search.ClearScrollRequest;
import org.elasticsearch.action.search.ClearScrollResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchResponseSections;
import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.search.ShardSearchFailure;
import org.elasticsearch.client.core.MainRequest;
import org.elasticsearch.client.core.MainResponse;
import org.elasticsearch.client.indexlifecycle.AllocateAction;
import org.elasticsearch.client.indexlifecycle.DeleteAction;
import org.elasticsearch.client.indexlifecycle.ForceMergeAction;
Expand All @@ -57,7 +55,6 @@
import org.elasticsearch.client.indexlifecycle.SetPriorityAction;
import org.elasticsearch.client.indexlifecycle.ShrinkAction;
import org.elasticsearch.client.indexlifecycle.UnfollowAction;
import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.common.CheckedFunction;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.Tuple;
Expand Down Expand Up @@ -176,9 +173,28 @@ public void testPingSocketTimeout() throws IOException {
}

public void testInfo() throws IOException {
MainResponse testInfo = new MainResponse("nodeName", Version.CURRENT, new ClusterName("clusterName"), "clusterUuid",
Build.CURRENT);
mockResponse(testInfo);
MainResponse testInfo = new MainResponse("nodeName", new MainResponse.Version("number", "buildFlavor", "buildType", "buildHash",
"buildDate", true, "luceneVersion", "minimumWireCompatibilityVersion", "minimumIndexCompatibilityVersion"),
"clusterName", "clusterUuid", "You Know, for Search");
mockResponse((builder, params) -> {
// taken from the server side MainResponse
builder.field("name", testInfo.getNodeName());
builder.field("cluster_name", testInfo.getClusterName());
builder.field("cluster_uuid", testInfo.getClusterUuid());
builder.startObject("version")
.field("number", testInfo.getVersion().getNumber())
.field("build_flavor", testInfo.getVersion().getBuildFlavor())
.field("build_type", testInfo.getVersion().getBuildType())
.field("build_hash", testInfo.getVersion().getBuildHash())
.field("build_date", testInfo.getVersion().getBuildDate())
.field("build_snapshot", testInfo.getVersion().isSnapshot())
.field("lucene_version", testInfo.getVersion().getLuceneVersion())
.field("minimum_wire_compatibility_version", testInfo.getVersion().getMinimumWireCompatibilityVersion())
.field("minimum_index_compatibility_version", testInfo.getVersion().getMinimumIndexCompatibilityVersion())
.endObject();
builder.field("tagline", testInfo.getTagline());
return builder;
});
MainResponse receivedInfo = restHighLevelClient.info(RequestOptions.DEFAULT);
assertEquals(testInfo, receivedInfo);
}
Expand Down
Loading

0 comments on commit fb5a065

Please sign in to comment.