Skip to content

Commit bb9d612

Browse files
authored
Show only committed cluster UUID in GET / (#114275)
Today we show `Metadata#clusterUUID` in the response to `GET /` regardless of whether this value is committed or not, which means that in theory users may see this value change even if nothing is going wrong. To avoid any doubt about the stability of this cluster UUID, this commit suppresses the cluster UUID in this API response until it is committed.
1 parent 4ecc5bd commit bb9d612

File tree

3 files changed

+31
-19
lines changed

3 files changed

+31
-19
lines changed

modules/rest-root/src/main/java/org/elasticsearch/rest/root/TransportMainAction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.elasticsearch.action.support.ActionFilters;
1515
import org.elasticsearch.action.support.TransportAction;
1616
import org.elasticsearch.cluster.ClusterState;
17+
import org.elasticsearch.cluster.metadata.Metadata;
1718
import org.elasticsearch.cluster.service.ClusterService;
1819
import org.elasticsearch.common.settings.Settings;
1920
import org.elasticsearch.common.util.concurrent.EsExecutors;
@@ -48,7 +49,7 @@ protected void doExecute(Task task, MainRequest request, ActionListener<MainResp
4849
nodeName,
4950
IndexVersion.current().luceneVersion().toString(),
5051
clusterState.getClusterName(),
51-
clusterState.metadata().clusterUUID(),
52+
clusterState.metadata().clusterUUIDCommitted() ? clusterState.metadata().clusterUUID() : Metadata.UNKNOWN_CLUSTER_UUID,
5253
Build.current()
5354
)
5455
);

modules/rest-root/src/test/java/org/elasticsearch/rest/root/MainActionTests.java

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@
99

1010
package org.elasticsearch.rest.root;
1111

12-
import org.elasticsearch.action.ActionListener;
1312
import org.elasticsearch.action.support.ActionFilters;
13+
import org.elasticsearch.action.support.ActionTestUtils;
1414
import org.elasticsearch.cluster.ClusterName;
1515
import org.elasticsearch.cluster.ClusterState;
1616
import org.elasticsearch.cluster.block.ClusterBlock;
1717
import org.elasticsearch.cluster.block.ClusterBlockLevel;
1818
import org.elasticsearch.cluster.block.ClusterBlocks;
19+
import org.elasticsearch.cluster.metadata.Metadata;
1920
import org.elasticsearch.cluster.service.ClusterService;
2021
import org.elasticsearch.common.settings.Settings;
2122
import org.elasticsearch.rest.RestStatus;
@@ -26,7 +27,7 @@
2627
import org.elasticsearch.transport.TransportService;
2728

2829
import java.util.Collections;
29-
import java.util.concurrent.atomic.AtomicReference;
30+
import java.util.concurrent.atomic.AtomicBoolean;
3031

3132
import static org.mockito.Mockito.mock;
3233
import static org.mockito.Mockito.times;
@@ -39,7 +40,7 @@ public void testMainActionClusterAvailable() {
3940
final ClusterService clusterService = mock(ClusterService.class);
4041
final ClusterName clusterName = new ClusterName("elasticsearch");
4142
final Settings settings = Settings.builder().put("node.name", "my-node").build();
42-
ClusterBlocks blocks;
43+
final ClusterBlocks blocks;
4344
if (randomBoolean()) {
4445
if (randomBoolean()) {
4546
blocks = ClusterBlocks.EMPTY_CLUSTER_BLOCK;
@@ -73,7 +74,12 @@ public void testMainActionClusterAvailable() {
7374
)
7475
.build();
7576
}
76-
ClusterState state = ClusterState.builder(clusterName).blocks(blocks).build();
77+
final Metadata.Builder metadata = new Metadata.Builder();
78+
if (randomBoolean()) {
79+
metadata.clusterUUID(randomUUID());
80+
metadata.clusterUUIDCommitted(randomBoolean());
81+
}
82+
final ClusterState state = ClusterState.builder(clusterName).metadata(metadata).blocks(blocks).build();
7783
when(clusterService.state()).thenReturn(state);
7884

7985
TransportService transportService = new TransportService(
@@ -85,21 +91,21 @@ public void testMainActionClusterAvailable() {
8591
null,
8692
Collections.emptySet()
8793
);
88-
TransportMainAction action = new TransportMainAction(settings, transportService, mock(ActionFilters.class), clusterService);
89-
AtomicReference<MainResponse> responseRef = new AtomicReference<>();
90-
action.doExecute(mock(Task.class), new MainRequest(), new ActionListener<>() {
91-
@Override
92-
public void onResponse(MainResponse mainResponse) {
93-
responseRef.set(mainResponse);
94-
}
95-
96-
@Override
97-
public void onFailure(Exception e) {
98-
logger.error("unexpected error", e);
99-
}
100-
});
94+
final AtomicBoolean listenerCalled = new AtomicBoolean();
95+
new TransportMainAction(settings, transportService, mock(ActionFilters.class), clusterService).doExecute(
96+
mock(Task.class),
97+
new MainRequest(),
98+
ActionTestUtils.assertNoFailureListener(mainResponse -> {
99+
assertNotNull(mainResponse);
100+
assertEquals(
101+
state.metadata().clusterUUIDCommitted() ? state.metadata().clusterUUID() : Metadata.UNKNOWN_CLUSTER_UUID,
102+
mainResponse.getClusterUuid()
103+
);
104+
assertFalse(listenerCalled.getAndSet(true));
105+
})
106+
);
101107

102-
assertNotNull(responseRef.get());
108+
assertTrue(listenerCalled.get());
103109
verify(clusterService, times(1)).state();
104110
}
105111
}

server/src/main/java/org/elasticsearch/cluster/metadata/Metadata.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,11 @@ public long version() {
695695
return this.version;
696696
}
697697

698+
/**
699+
* @return A UUID which identifies this cluster. Nodes record the UUID of the cluster they first join on disk, and will then refuse to
700+
* join clusters with different UUIDs. Note that when the cluster is forming for the first time this value may not yet be committed,
701+
* and therefore it may change. Check {@link #clusterUUIDCommitted()} to verify that the value is committed if needed.
702+
*/
698703
public String clusterUUID() {
699704
return this.clusterUUID;
700705
}

0 commit comments

Comments
 (0)