Skip to content

Commit

Permalink
Include node roles in cluster state JSON response
Browse files Browse the repository at this point in the history
Today the response to `GET _cluster/state` does not include the roles of
the nodes in the cluster. In the past this made sense, roles were
relatively unchanging things that could be determined from elsewhere.
These days we have an increasingly rich collection of roles, with
nontrivial BWC implications, so it is important for debugging to be able
to see the specific roles as viewed by the master. This commit adds the
role names to the cluster state API output.

Relates elastic#71385
Backport of elastic#71386
  • Loading branch information
DaveCTurner committed Apr 7, 2021
1 parent da7f2cf commit acf77d6
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 6 deletions.
4 changes: 3 additions & 1 deletion docs/reference/indices/shard-stores.asciidoc
Expand Up @@ -162,7 +162,8 @@ The API returns the following response:
"name": "node_t0",
"ephemeral_id": "9NlXRFGCT1m8tkvYCMK-8A",
"transport_address": "local[1]",
"attributes": {}
"attributes": {},
"roles": [...]
},
"allocation_id": "2iNySv_OQVePRX-yaRH_lQ", <4>
"allocation": "primary|replica|unused" <5>
Expand All @@ -179,6 +180,7 @@ The API returns the following response:
// TESTRESPONSE[s/"sPa3OgxLSYGvQ4oPs-Tajw"/\$node_name/]
// TESTRESPONSE[s/: "[^"]*"/: $body.$_path/]
// TESTRESPONSE[s/"attributes": \{[^}]*\}/"attributes": $body.$_path/]
// TESTRESPONSE[s/"roles": \[[^]]*\]/"roles": $body.$_path/]



Expand Down
Expand Up @@ -507,6 +507,12 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
}
builder.endObject();

builder.startArray("roles");
for (DiscoveryNodeRole role : roles) {
builder.value(role.roleName());
}
builder.endArray();

builder.endObject();
return builder;
}
Expand Down
Expand Up @@ -68,7 +68,18 @@ public void testToXContent() throws IOException {
" \"name\" : \"\",\n" +
" \"ephemeral_id\" : \"" + node0.getEphemeralId() + "\",\n" +
" \"transport_address\" : \"0.0.0.0:9000\",\n" +
" \"attributes\" : { }\n" +
" \"attributes\" : { },\n" +
" \"roles\" : [\n" +
" \"data\",\n" +
" \"data_cold\",\n" +
" \"data_content\",\n" +
" \"data_frozen\",\n" +
" \"data_hot\",\n" +
" \"data_warm\",\n" +
" \"ingest\",\n" +
" \"master\",\n" +
" \"remote_cluster_client\"\n" +
" ]\n" +
" }\n" +
" },\n" +
" \"metadata\" : {\n" +
Expand Down
Expand Up @@ -150,7 +150,18 @@ public void testToXContent() throws IOException {
" \"name\" : \"\",\n" +
" \"ephemeral_id\" : \"" + ephemeralId + "\",\n" +
" \"transport_address\" : \"127.0.0.1:111\",\n" +
" \"attributes\" : { }\n" +
" \"attributes\" : { },\n" +
" \"roles\" : [\n" +
" \"data\",\n" +
" \"data_cold\",\n" +
" \"data_content\",\n" +
" \"data_frozen\",\n" +
" \"data_hot\",\n" +
" \"data_warm\",\n" +
" \"ingest\",\n" +
" \"master\",\n" +
" \"remote_cluster_client\"\n" +
" ]\n" +
" }\n" +
" },\n" +
" \"metadata\" : {\n" +
Expand Down Expand Up @@ -345,7 +356,18 @@ public void testToXContent_FlatSettingTrue_ReduceMappingFalse() throws IOExcepti
" \"name\" : \"\",\n" +
" \"ephemeral_id\" : \"" + ephemeralId + "\",\n" +
" \"transport_address\" : \"127.0.0.1:111\",\n" +
" \"attributes\" : { }\n" +
" \"attributes\" : { },\n" +
" \"roles\" : [\n" +
" \"data\",\n" +
" \"data_cold\",\n" +
" \"data_content\",\n" +
" \"data_frozen\",\n" +
" \"data_hot\",\n" +
" \"data_warm\",\n" +
" \"ingest\",\n" +
" \"master\",\n" +
" \"remote_cluster_client\"\n" +
" ]\n" +
" }\n" +
" },\n" +
" \"metadata\" : {\n" +
Expand Down Expand Up @@ -533,7 +555,18 @@ public void testToXContent_FlatSettingFalse_ReduceMappingTrue() throws IOExcepti
" \"name\" : \"\",\n" +
" \"ephemeral_id\" : \"" + ephemeralId + "\",\n" +
" \"transport_address\" : \"127.0.0.1:111\",\n" +
" \"attributes\" : { }\n" +
" \"attributes\" : { },\n" +
" \"roles\" : [\n" +
" \"data\",\n" +
" \"data_cold\",\n" +
" \"data_content\",\n" +
" \"data_frozen\",\n" +
" \"data_hot\",\n" +
" \"data_warm\",\n" +
" \"ingest\",\n" +
" \"master\",\n" +
" \"remote_cluster_client\"\n" +
" ]\n" +
" }\n" +
" },\n" +
" \"metadata\" : {\n" +
Expand Down
Expand Up @@ -9,16 +9,21 @@
package org.elasticsearch.cluster.node;

import org.elasticsearch.Version;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.test.ESTestCase;

import java.net.InetAddress;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

Expand All @@ -27,10 +32,13 @@
import static org.elasticsearch.test.NodeRoles.nonRemoteClusterClientNode;
import static org.elasticsearch.test.NodeRoles.remoteClusterClientNode;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.anEmptyMap;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;

Expand Down Expand Up @@ -164,4 +172,41 @@ public void testDiscoveryNodeDescriptionWithoutAttributes() {
assertThat(descriptionWithoutAttributes, not(containsString("test-attr")));
}

public void testDiscoveryNodeToXContent() {
final TransportAddress transportAddress = buildNewFakeTransportAddress();
final DiscoveryNode node = new DiscoveryNode(
"test-name",
"test-id",
"test-ephemeral-id",
"test-hostname",
"test-hostaddr",
transportAddress,
Collections.singletonMap("test-attr", "val"),
DiscoveryNodeRole.BUILT_IN_ROLES,
Version.CURRENT);

final String jsonString = Strings.toString(node, randomBoolean(), randomBoolean());
final Map<String, Object> topLevelMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), jsonString, randomBoolean());

assertThat(topLevelMap.toString(), topLevelMap.size(), equalTo(1));
assertTrue(topLevelMap.toString(), topLevelMap.containsKey("test-id"));

@SuppressWarnings("unchecked")
final Map<String, Object> detailsMap = (Map<String, Object>) topLevelMap.get("test-id");

assertThat(topLevelMap.toString(), detailsMap.remove("name"), equalTo("test-name"));
assertThat(topLevelMap.toString(), detailsMap.remove("ephemeral_id"), equalTo("test-ephemeral-id"));
assertThat(topLevelMap.toString(), detailsMap.remove("transport_address"), equalTo(transportAddress.toString()));

@SuppressWarnings("unchecked")
final Map<String, Object> attributes = (Map<String, Object>) detailsMap.remove("attributes");
assertThat(topLevelMap.toString(), attributes.get("test-attr"), equalTo("val"));

@SuppressWarnings("unchecked")
final List<String> roles = (List<String>) detailsMap.remove("roles");
assertThat(roles, hasItems("master", "data_content", "remote_cluster_client"));

assertThat(detailsMap.toString(), detailsMap, anEmptyMap());
}

}
Expand Up @@ -601,7 +601,10 @@ public void testToXContent() throws IOException {
+ "\"transport_address\":\"0.0.0.0:9300\","
+ "\"attributes\":{"
+ "\"attr\":\"value\""
+ "}"
+ "},"
+ "\"roles\":["
+ "\"master\""
+ "]"
+ "}"
+ "}"
+ "},"
Expand Down

0 comments on commit acf77d6

Please sign in to comment.