Fallback to '/' info call to fetch cluster version

The `_cat/nodes` API might not be available in all clusters for instance
if they have authorization enabled. This change falls back to the previously
used method of using the '/' endpoint to fetch the nodes version, this is best
effort and will emit a warning.
This commit is contained in:
Simon Willnauer 2016-10-28 16:18:41 +02:00
parent 36c86c2b00
commit 9598616dfe
1 changed files with 56 additions and 23 deletions

View File

@ -67,39 +67,72 @@ public class ClientYamlTestClient {
assert hosts.size() > 0;
this.restSpec = restSpec;
this.restClient = restClient;
Tuple<Version, Version> versionTuple = readMasterAndMinNodeVersion();
Tuple<Version, Version> versionTuple = readMasterAndMinNodeVersion(hosts.size());
this.esVersion = versionTuple.v1();
Version masterVersion = versionTuple.v2();
// this will be logged in each test such that if something fails we get it in the logs for each test
logger.info("initializing client, minimum es version: [{}] master version: [{}] hosts: {}", esVersion, masterVersion, hosts);
}
private Tuple<Version, Version> readMasterAndMinNodeVersion() throws IOException {
// we simply go to the _cat/nodes API and parse all versions in the cluster
Response response = restClient.performRequest("GET", "/_cat/nodes", Collections.singletonMap("h", "version,master"));
ClientYamlTestResponse restTestResponse = new ClientYamlTestResponse(response);
String nodesCatResponse = restTestResponse.getBodyAsString();
String[] split = nodesCatResponse.split("\n");
Version version = null;
Version masterVersion = null;
for (String perNode : split) {
final String[] versionAndMaster = perNode.split(" ");
assert versionAndMaster.length == 2 : "invalid line: " + perNode + " length: " + versionAndMaster.length;
final Version currentVersion = Version.fromString(versionAndMaster[0]);
final boolean master = versionAndMaster[1].trim().equals("*");
if (master) {
assert masterVersion == null;
masterVersion = currentVersion;
}
if (version == null) {
version = currentVersion;
} else {
if (version.onOrAfter(currentVersion)) {
private Tuple<Version, Version> readMasterAndMinNodeVersion(int numHosts) throws IOException {
try {
// we simply go to the _cat/nodes API and parse all versions in the cluster
Response response = restClient.performRequest("GET", "/_cat/nodes", Collections.singletonMap("h", "version,master"));
ClientYamlTestResponse restTestResponse = new ClientYamlTestResponse(response);
String nodesCatResponse = restTestResponse.getBodyAsString();
String[] split = nodesCatResponse.split("\n");
Version version = null;
Version masterVersion = null;
for (String perNode : split) {
final String[] versionAndMaster = perNode.split(" ");
assert versionAndMaster.length == 2 : "invalid line: " + perNode + " length: " + versionAndMaster.length;
final Version currentVersion = Version.fromString(versionAndMaster[0]);
final boolean master = versionAndMaster[1].trim().equals("*");
if (master) {
assert masterVersion == null;
masterVersion = currentVersion;
}
if (version == null) {
version = currentVersion;
} else if (version.onOrAfter(currentVersion)) {
version = currentVersion;
}
}
return new Tuple<>(version, masterVersion);
} catch (ResponseException ex) {
if (ex.getResponse().getStatusLine().getStatusCode() == 403) {
logger.warn("Fallback to simple info '/' request, _cat/nodes is not authorized");
final Version version = readAndCheckVersion(numHosts);
return new Tuple<>(version, version);
}
throw ex;
}
return new Tuple<>(version, masterVersion);
}
private Version readAndCheckVersion(int numHosts) throws IOException {
ClientYamlSuiteRestApi restApi = restApi("info");
assert restApi.getPaths().size() == 1;
assert restApi.getMethods().size() == 1;
Version version = null;
for (int i = 0; i < numHosts; i++) {
//we don't really use the urls here, we rely on the client doing round-robin to touch all the nodes in the cluster
String method = restApi.getMethods().get(0);
String endpoint = restApi.getPaths().get(0);
Response response = restClient.performRequest(method, endpoint);
ClientYamlTestResponse restTestResponse = new ClientYamlTestResponse(response);
Object latestVersion = restTestResponse.evaluate("version.number");
if (latestVersion == null) {
throw new RuntimeException("elasticsearch version not found in the response");
}
final Version currentVersion = Version.fromString(restTestResponse.evaluate("version.number").toString());
if (version == null) {
version = currentVersion;
} else if (version.onOrAfter(currentVersion)) {
version = currentVersion;
}
}
return version;
}
public Version getEsVersion() {