Browse Source

_cluster/state should always return cluster_uuid (#30143)

Currently, the only way to get the REST response for the `/_cluster/state`
call to return the `cluster_uuid` is to request the `metadata` metrics,
which is one of the most expensive response structures. However, external
monitoring agents will likely want the `cluster_uuid` to correlate the
response with other API responses whether or not they want cluster
metadata.
Chris Earle 7 years ago
parent
commit
725a5af2c6

+ 6 - 0
docs/reference/cluster/state.asciidoc

@@ -15,6 +15,12 @@ of the cluster state (its size when serialized for transmission over
 the network), and the cluster state itself, which can be filtered to
 only retrieve the parts of interest, as described below.
 
+The cluster's `cluster_uuid` is also returned as part of the top-level
+response, in addition to the `metadata` section. added[6.4.0]
+
+NOTE: While the cluster is still forming, it is possible for the `cluster_uuid`
+      to be `_na_` as well as the cluster state's version to be `-1`.
+
 By default, the cluster state request is routed to the master node, to
 ensure that the latest cluster state is returned.   
 For debugging purposes, you can retrieve the cluster state local to a

+ 16 - 1
rest-api-spec/src/main/resources/rest-api-spec/test/cluster.state/10_basic.yml

@@ -2,7 +2,7 @@
 "get cluster state":
   - do:
       cluster.state: {}
-  
+
   - is_true: master_node
 
 ---
@@ -18,3 +18,18 @@
   - is_true: master_node
   - gte: { compressed_size_in_bytes: 50 }
   - is_true: compressed_size
+
+---
+"get cluster state returns cluster_uuid at the top level":
+  - skip:
+      version:  " - 6.99.99"
+      reason:   "cluster state including cluster_uuid at the top level is new in v6.4.0 and higher"
+
+  - do:
+      cluster.state:
+        human: true
+
+  - is_true: cluster_uuid
+  - is_true: master_node
+  - gte: { compressed_size_in_bytes: 50 }
+  - is_true: compressed_size

+ 16 - 0
rest-api-spec/src/main/resources/rest-api-spec/test/cluster.state/20_filtering.yml

@@ -156,3 +156,19 @@ setup:
   - is_true: routing_table.indices.index1
   - is_true: metadata.indices.index2
   - is_true: routing_table.indices.index2
+
+---
+"Filtering the cluster state returns cluster_uuid at the top level regardless of metric filters":
+  - skip:
+      version:  " - 6.99.99"
+      reason:   "cluster state including cluster_uuid at the top level is new in v6.4.0 and higher"
+
+  - do:
+      cluster.state:
+        metric: [ master_node, version, metadata ]
+
+  - is_true: cluster_uuid
+  - is_true: master_node
+  - is_true: version
+  - is_true: state_uuid
+  - is_true: metadata

+ 3 - 0
server/src/main/java/org/elasticsearch/cluster/ClusterState.java

@@ -326,6 +326,9 @@ public class ClusterState implements ToXContentFragment, Diffable<ClusterState>
     public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
         EnumSet<Metric> metrics = Metric.parseString(params.param("metric", "_all"), true);
 
+        // always provide the cluster_uuid as part of the top-level response (also part of the metadata response)
+        builder.field("cluster_uuid", metaData().clusterUUID());
+
         if (metrics.contains(Metric.VERSION)) {
             builder.field("version", version);
             builder.field("state_uuid", stateUUID);

+ 3 - 0
server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java

@@ -69,6 +69,7 @@ public class ClusterRerouteResponseTests extends ESTestCase {
             assertEquals("{\n" +
                     "  \"acknowledged\" : true,\n" +
                     "  \"state\" : {\n" +
+                    "    \"cluster_uuid\" : \"_na_\",\n" +
                     "    \"version\" : 0,\n" +
                     "    \"state_uuid\" : \"" + clusterState.stateUUID() + "\",\n" +
                     "    \"master_node\" : \"node0\",\n" +
@@ -136,6 +137,7 @@ public class ClusterRerouteResponseTests extends ESTestCase {
             assertEquals("{\n" +
                     "  \"acknowledged\" : true,\n" +
                     "  \"state\" : {\n" +
+                    "    \"cluster_uuid\" : \"_na_\",\n" +
                     "    \"version\" : 0,\n" +
                     "    \"state_uuid\" : \"" + clusterState.stateUUID() + "\",\n" +
                     "    \"master_node\" : \"node0\"\n" +
@@ -168,6 +170,7 @@ public class ClusterRerouteResponseTests extends ESTestCase {
             assertEquals("{\n" +
                     "  \"acknowledged\" : true,\n" +
                     "  \"state\" : {\n" +
+                    "    \"cluster_uuid\" : \"_na_\",\n" +
                     "    \"metadata\" : {\n" +
                     "      \"cluster_uuid\" : \"_na_\",\n" +
                     "      \"templates\" : { },\n" +

+ 4 - 0
x-pack/plugin/monitoring/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsMonitoringDocTests.java

@@ -17,6 +17,7 @@ import org.elasticsearch.action.admin.indices.stats.ShardStats;
 import org.elasticsearch.cluster.ClusterName;
 import org.elasticsearch.cluster.ClusterState;
 import org.elasticsearch.cluster.health.ClusterHealthStatus;
+import org.elasticsearch.cluster.metadata.MetaData;
 import org.elasticsearch.cluster.node.DiscoveryNode;
 import org.elasticsearch.cluster.node.DiscoveryNodes;
 import org.elasticsearch.cluster.routing.ShardRouting;
@@ -188,6 +189,7 @@ public class ClusterStatsMonitoringDocTests extends BaseMonitoringDocTestCase<Cl
 
     @Override
     public void testToXContent() throws IOException {
+        final String clusterUuid = "_cluster";
         final ClusterName clusterName = new ClusterName("_cluster_name");
         final TransportAddress transportAddress = new TransportAddress(TransportAddress.META_ADDRESS, 9300);
         final DiscoveryNode discoveryNode = new DiscoveryNode("_node_name",
@@ -201,6 +203,7 @@ public class ClusterStatsMonitoringDocTests extends BaseMonitoringDocTestCase<Cl
                                                                 Version.V_6_0_0_beta1);
 
         final ClusterState clusterState = ClusterState.builder(clusterName)
+                                                        .metaData(MetaData.builder().clusterUUID(clusterUuid).build())
                                                         .stateUUID("_state_uuid")
                                                         .version(12L)
                                                         .nodes(DiscoveryNodes.builder()
@@ -500,6 +503,7 @@ public class ClusterStatsMonitoringDocTests extends BaseMonitoringDocTestCase<Cl
                   + "\"cluster_state\":{"
                     + "\"nodes_hash\":1314980060,"
                     + "\"status\":\"green\","
+                    + "\"cluster_uuid\":\"_cluster\","
                     + "\"version\":12,"
                     + "\"state_uuid\":\"_state_uuid\","
                     + "\"master_node\":\"_node\","