Skip to content

Commit fb5a065

Browse files
committed
HLRC: Convert xpack methods to client side objects (#40705)
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
1 parent 9e8499d commit fb5a065

File tree

10 files changed

+361
-38
lines changed

10 files changed

+361
-38
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/RestHighLevelClient.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@
4444
import org.elasticsearch.action.get.MultiGetResponse;
4545
import org.elasticsearch.action.index.IndexRequest;
4646
import org.elasticsearch.action.index.IndexResponse;
47-
import org.elasticsearch.action.main.MainRequest;
48-
import org.elasticsearch.action.main.MainResponse;
4947
import org.elasticsearch.action.search.ClearScrollRequest;
5048
import org.elasticsearch.action.search.ClearScrollResponse;
5149
import org.elasticsearch.action.search.MultiSearchRequest;
@@ -58,6 +56,8 @@
5856
import org.elasticsearch.action.update.UpdateResponse;
5957
import org.elasticsearch.client.core.CountRequest;
6058
import org.elasticsearch.client.core.CountResponse;
59+
import org.elasticsearch.client.core.MainRequest;
60+
import org.elasticsearch.client.core.MainResponse;
6161
import org.elasticsearch.client.core.MultiTermVectorsRequest;
6262
import org.elasticsearch.client.core.MultiTermVectorsResponse;
6363
import org.elasticsearch.client.core.TermVectorsRequest;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client.core;
21+
22+
import org.elasticsearch.client.Validatable;
23+
24+
public class MainRequest implements Validatable {
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client.core;
21+
22+
import org.elasticsearch.common.ParseField;
23+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
24+
import org.elasticsearch.common.xcontent.XContentParser;
25+
26+
import java.util.Objects;
27+
28+
public class MainResponse {
29+
30+
@SuppressWarnings("unchecked")
31+
private static ConstructingObjectParser<MainResponse, Void> PARSER =
32+
new ConstructingObjectParser<>(MainResponse.class.getName(), true,
33+
args -> {
34+
return new MainResponse((String) args[0], (Version) args[1], (String) args[2], (String) args[3], (String) args[4]);
35+
}
36+
);
37+
38+
static {
39+
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("name"));
40+
PARSER.declareObject(ConstructingObjectParser.constructorArg(), Version.PARSER, new ParseField("version"));
41+
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("cluster_name"));
42+
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("cluster_uuid"));
43+
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("tagline"));
44+
45+
}
46+
47+
private final String nodeName;
48+
private final Version version;
49+
private final String clusterName;
50+
private final String clusterUuid;
51+
private final String tagline;
52+
53+
public MainResponse(String nodeName, Version version, String clusterName, String clusterUuid, String tagline) {
54+
this.nodeName = nodeName;
55+
this.version = version;
56+
this.clusterName = clusterName;
57+
this.clusterUuid = clusterUuid;
58+
this.tagline = tagline;
59+
}
60+
61+
public String getNodeName() {
62+
return nodeName;
63+
}
64+
65+
public Version getVersion() {
66+
return version;
67+
}
68+
69+
public String getClusterName() {
70+
return clusterName;
71+
}
72+
73+
public String getClusterUuid() {
74+
return clusterUuid;
75+
}
76+
77+
public String getTagline() {
78+
return tagline;
79+
}
80+
81+
public static MainResponse fromXContent(XContentParser parser) {
82+
return PARSER.apply(parser, null);
83+
}
84+
85+
@Override
86+
public boolean equals(Object o) {
87+
if (this == o) return true;
88+
if (o == null || getClass() != o.getClass()) return false;
89+
MainResponse that = (MainResponse) o;
90+
return nodeName.equals(that.nodeName) &&
91+
version.equals(that.version) &&
92+
clusterName.equals(that.clusterName) &&
93+
clusterUuid.equals(that.clusterUuid) &&
94+
tagline.equals(that.tagline);
95+
}
96+
97+
@Override
98+
public int hashCode() {
99+
return Objects.hash(nodeName, version, clusterName, clusterUuid, tagline);
100+
}
101+
102+
public static class Version {
103+
@SuppressWarnings("unchecked")
104+
private static ConstructingObjectParser<Version, Void> PARSER =
105+
new ConstructingObjectParser<>(Version.class.getName(), true,
106+
args -> {
107+
return new Version((String) args[0], (String) args[1], (String) args[2], (String) args[3], (String) args[4],
108+
(Boolean) args[5], (String) args[6], (String) args[7], (String) args[8]);
109+
}
110+
);
111+
112+
static {
113+
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("number"));
114+
PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("build_flavor"));
115+
PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), new ParseField("build_type"));
116+
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("build_hash"));
117+
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("build_date"));
118+
PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), new ParseField("build_snapshot"));
119+
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("lucene_version"));
120+
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("minimum_wire_compatibility_version"));
121+
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("minimum_index_compatibility_version"));
122+
}
123+
private final String number;
124+
private final String buildFlavor;
125+
private final String buildType;
126+
private final String buildHash;
127+
private final String buildDate;
128+
private final boolean isSnapshot;
129+
private final String luceneVersion;
130+
private final String minimumWireCompatibilityVersion;
131+
private final String minimumIndexCompatibilityVersion;
132+
133+
public Version(String number, String buildFlavor, String buildType, String buildHash, String buildDate, boolean isSnapshot,
134+
String luceneVersion, String minimumWireCompatibilityVersion, String minimumIndexCompatibilityVersion) {
135+
this.number = number;
136+
this.buildFlavor = buildFlavor;
137+
this.buildType = buildType;
138+
this.buildHash = buildHash;
139+
this.buildDate = buildDate;
140+
this.isSnapshot = isSnapshot;
141+
this.luceneVersion = luceneVersion;
142+
this.minimumWireCompatibilityVersion = minimumWireCompatibilityVersion;
143+
this.minimumIndexCompatibilityVersion = minimumIndexCompatibilityVersion;
144+
}
145+
146+
public String getNumber() {
147+
return number;
148+
}
149+
150+
public String getBuildFlavor() {
151+
return buildFlavor;
152+
}
153+
154+
public String getBuildType() {
155+
return buildType;
156+
}
157+
158+
public String getBuildHash() {
159+
return buildHash;
160+
}
161+
162+
public String getBuildDate() {
163+
return buildDate;
164+
}
165+
166+
public boolean isSnapshot() {
167+
return isSnapshot;
168+
}
169+
170+
public String getLuceneVersion() {
171+
return luceneVersion;
172+
}
173+
174+
public String getMinimumWireCompatibilityVersion() {
175+
return minimumWireCompatibilityVersion;
176+
}
177+
178+
public String getMinimumIndexCompatibilityVersion() {
179+
return minimumIndexCompatibilityVersion;
180+
}
181+
182+
@Override
183+
public boolean equals(Object o) {
184+
if (this == o) return true;
185+
if (o == null || getClass() != o.getClass()) return false;
186+
Version version = (Version) o;
187+
return isSnapshot == version.isSnapshot &&
188+
number.equals(version.number) &&
189+
Objects.equals(buildFlavor, version.buildFlavor) &&
190+
Objects.equals(buildType, version.buildType) &&
191+
buildHash.equals(version.buildHash) &&
192+
buildDate.equals(version.buildDate) &&
193+
luceneVersion.equals(version.luceneVersion) &&
194+
minimumWireCompatibilityVersion.equals(version.minimumWireCompatibilityVersion) &&
195+
minimumIndexCompatibilityVersion.equals(version.minimumIndexCompatibilityVersion);
196+
}
197+
198+
@Override
199+
public int hashCode() {
200+
return Objects.hash(number, buildFlavor, buildType, buildHash, buildDate, isSnapshot, luceneVersion,
201+
minimumWireCompatibilityVersion, minimumIndexCompatibilityVersion);
202+
}
203+
}
204+
}

client/rest-high-level/src/test/java/org/elasticsearch/client/CCRIT.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ public void testForgetFollower() throws IOException {
228228
assertTrue(putFollowResponse.isFollowIndexShardsAcked());
229229
assertTrue(putFollowResponse.isIndexFollowingStarted());
230230

231-
final String clusterName = highLevelClient().info(RequestOptions.DEFAULT).getClusterName().value();
231+
final String clusterName = highLevelClient().info(RequestOptions.DEFAULT).getClusterName();
232232

233233
final Request statsRequest = new Request("GET", "/follower/_stats");
234234
final Response statsResponse = client().performRequest(statsRequest);

client/rest-high-level/src/test/java/org/elasticsearch/client/PingAndInfoIT.java

+11-11
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
package org.elasticsearch.client;
2121

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

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

5959
public void testXPackInfo() throws IOException {
@@ -64,7 +64,7 @@ public void testXPackInfo() throws IOException {
6464

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

67-
assertEquals(mainResponse.getBuild().shortHash(), info.getBuildInfo().getHash());
67+
assertEquals(mainResponse.getVersion().getBuildHash(), info.getBuildInfo().getHash());
6868

6969
assertEquals("trial", info.getLicenseInfo().getType());
7070
assertEquals("trial", info.getLicenseInfo().getMode());
@@ -84,7 +84,7 @@ public void testXPackInfo() throws IOException {
8484
assertNotNull(ml.description());
8585
assertTrue(ml.available());
8686
assertTrue(ml.enabled());
87-
assertEquals(mainResponse.getBuild().getQualifiedVersion(), ml.nativeCodeInfo().get("version").toString());
87+
assertEquals(mainResponse.getVersion().getNumber(), ml.nativeCodeInfo().get("version").toString());
8888
}
8989

9090
public void testXPackInfoEmptyRequest() throws IOException {

client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java

+24-8
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,18 @@
3333
import org.apache.http.message.BasicStatusLine;
3434
import org.apache.http.nio.entity.NByteArrayEntity;
3535
import org.apache.http.nio.entity.NStringEntity;
36-
import org.elasticsearch.Build;
3736
import org.elasticsearch.ElasticsearchException;
38-
import org.elasticsearch.Version;
3937
import org.elasticsearch.action.ActionListener;
4038
import org.elasticsearch.action.ActionRequest;
4139
import org.elasticsearch.action.ActionRequestValidationException;
42-
import org.elasticsearch.action.main.MainRequest;
43-
import org.elasticsearch.action.main.MainResponse;
4440
import org.elasticsearch.action.search.ClearScrollRequest;
4541
import org.elasticsearch.action.search.ClearScrollResponse;
4642
import org.elasticsearch.action.search.SearchResponse;
4743
import org.elasticsearch.action.search.SearchResponseSections;
4844
import org.elasticsearch.action.search.SearchScrollRequest;
4945
import org.elasticsearch.action.search.ShardSearchFailure;
46+
import org.elasticsearch.client.core.MainRequest;
47+
import org.elasticsearch.client.core.MainResponse;
5048
import org.elasticsearch.client.indexlifecycle.AllocateAction;
5149
import org.elasticsearch.client.indexlifecycle.DeleteAction;
5250
import org.elasticsearch.client.indexlifecycle.ForceMergeAction;
@@ -57,7 +55,6 @@
5755
import org.elasticsearch.client.indexlifecycle.SetPriorityAction;
5856
import org.elasticsearch.client.indexlifecycle.ShrinkAction;
5957
import org.elasticsearch.client.indexlifecycle.UnfollowAction;
60-
import org.elasticsearch.cluster.ClusterName;
6158
import org.elasticsearch.common.CheckedFunction;
6259
import org.elasticsearch.common.bytes.BytesReference;
6360
import org.elasticsearch.common.collect.Tuple;
@@ -176,9 +173,28 @@ public void testPingSocketTimeout() throws IOException {
176173
}
177174

178175
public void testInfo() throws IOException {
179-
MainResponse testInfo = new MainResponse("nodeName", Version.CURRENT, new ClusterName("clusterName"), "clusterUuid",
180-
Build.CURRENT);
181-
mockResponse(testInfo);
176+
MainResponse testInfo = new MainResponse("nodeName", new MainResponse.Version("number", "buildFlavor", "buildType", "buildHash",
177+
"buildDate", true, "luceneVersion", "minimumWireCompatibilityVersion", "minimumIndexCompatibilityVersion"),
178+
"clusterName", "clusterUuid", "You Know, for Search");
179+
mockResponse((builder, params) -> {
180+
// taken from the server side MainResponse
181+
builder.field("name", testInfo.getNodeName());
182+
builder.field("cluster_name", testInfo.getClusterName());
183+
builder.field("cluster_uuid", testInfo.getClusterUuid());
184+
builder.startObject("version")
185+
.field("number", testInfo.getVersion().getNumber())
186+
.field("build_flavor", testInfo.getVersion().getBuildFlavor())
187+
.field("build_type", testInfo.getVersion().getBuildType())
188+
.field("build_hash", testInfo.getVersion().getBuildHash())
189+
.field("build_date", testInfo.getVersion().getBuildDate())
190+
.field("build_snapshot", testInfo.getVersion().isSnapshot())
191+
.field("lucene_version", testInfo.getVersion().getLuceneVersion())
192+
.field("minimum_wire_compatibility_version", testInfo.getVersion().getMinimumWireCompatibilityVersion())
193+
.field("minimum_index_compatibility_version", testInfo.getVersion().getMinimumIndexCompatibilityVersion())
194+
.endObject();
195+
builder.field("tagline", testInfo.getTagline());
196+
return builder;
197+
});
182198
MainResponse receivedInfo = restHighLevelClient.info(RequestOptions.DEFAULT);
183199
assertEquals(testInfo, receivedInfo);
184200
}

0 commit comments

Comments
 (0)