|
20 | 20 |
|
21 | 21 | import org.apache.logging.log4j.Level;
|
22 | 22 | import org.elasticsearch.Version;
|
| 23 | +import org.elasticsearch.action.ActionListenerResponseHandler; |
| 24 | +import org.elasticsearch.action.support.PlainActionFuture; |
| 25 | +import org.elasticsearch.cluster.ClusterName; |
| 26 | +import org.elasticsearch.cluster.ClusterState; |
23 | 27 | import org.elasticsearch.cluster.NotMasterException;
|
| 28 | +import org.elasticsearch.cluster.metadata.MetaData; |
24 | 29 | import org.elasticsearch.cluster.node.DiscoveryNode;
|
25 | 30 | import org.elasticsearch.common.settings.Settings;
|
| 31 | +import org.elasticsearch.discovery.zen.MembershipAction; |
26 | 32 | import org.elasticsearch.test.ESTestCase;
|
27 | 33 | import org.elasticsearch.test.transport.CapturingTransport;
|
28 | 34 | import org.elasticsearch.test.transport.CapturingTransport.CapturedRequest;
|
| 35 | +import org.elasticsearch.test.transport.MockTransport; |
29 | 36 | import org.elasticsearch.transport.RemoteTransportException;
|
30 | 37 | import org.elasticsearch.transport.TransportException;
|
31 | 38 | import org.elasticsearch.transport.TransportResponse;
|
|
35 | 42 | import java.util.Optional;
|
36 | 43 |
|
37 | 44 | import static org.elasticsearch.node.Node.NODE_NAME_SETTING;
|
| 45 | +import static org.hamcrest.Matchers.containsString; |
38 | 46 | import static org.hamcrest.Matchers.equalTo;
|
39 | 47 | import static org.hamcrest.core.Is.is;
|
40 | 48 |
|
@@ -131,4 +139,59 @@ public void testFailedJoinAttemptLogLevel() {
|
131 | 139 | new RemoteTransportException("caused by NotMasterException",
|
132 | 140 | new NotMasterException("test"))), is(Level.DEBUG));
|
133 | 141 | }
|
| 142 | + |
| 143 | + public void testJoinValidationRejectsMismatchedClusterUUID() { |
| 144 | + DeterministicTaskQueue deterministicTaskQueue = new DeterministicTaskQueue( |
| 145 | + Settings.builder().put(NODE_NAME_SETTING.getKey(), "node0").build(), random()); |
| 146 | + MockTransport mockTransport = new MockTransport(); |
| 147 | + DiscoveryNode localNode = new DiscoveryNode("node0", buildNewFakeTransportAddress(), Version.CURRENT); |
| 148 | + |
| 149 | + final ClusterState localClusterState = ClusterState.builder(ClusterName.DEFAULT).metaData(MetaData.builder() |
| 150 | + .generateClusterUuidIfNeeded().clusterUUIDCommitted(true)).build(); |
| 151 | + |
| 152 | + TransportService transportService = mockTransport.createTransportService(Settings.EMPTY, |
| 153 | + deterministicTaskQueue.getThreadPool(), TransportService.NOOP_TRANSPORT_INTERCEPTOR, |
| 154 | + x -> localNode, null, Collections.emptySet()); |
| 155 | + new JoinHelper(Settings.EMPTY, null, null, transportService, () -> 0L, () -> localClusterState, |
| 156 | + (joinRequest, joinCallback) -> { throw new AssertionError(); }, startJoinRequest -> { throw new AssertionError(); }, |
| 157 | + Collections.emptyList()); // registers request handler |
| 158 | + transportService.start(); |
| 159 | + transportService.acceptIncomingRequests(); |
| 160 | + |
| 161 | + { |
| 162 | + final ClusterState otherClusterState = ClusterState.builder(ClusterName.DEFAULT).metaData(MetaData.builder() |
| 163 | + .generateClusterUuidIfNeeded()).build(); |
| 164 | + |
| 165 | + final PlainActionFuture<TransportResponse.Empty> future = new PlainActionFuture<>(); |
| 166 | + transportService.sendRequest(localNode, JoinHelper.VALIDATE_JOIN_ACTION_NAME, |
| 167 | + new ValidateJoinRequest(otherClusterState), |
| 168 | + new ActionListenerResponseHandler<>(future, in -> TransportResponse.Empty.INSTANCE)); |
| 169 | + deterministicTaskQueue.runAllTasks(); |
| 170 | + |
| 171 | + final CoordinationStateRejectedException coordinationStateRejectedException |
| 172 | + = expectThrows(CoordinationStateRejectedException.class, future::actionGet); |
| 173 | + assertThat(coordinationStateRejectedException.getMessage(), |
| 174 | + containsString("join validation on cluster state with a different cluster uuid")); |
| 175 | + assertThat(coordinationStateRejectedException.getMessage(), containsString(localClusterState.metaData().clusterUUID())); |
| 176 | + assertThat(coordinationStateRejectedException.getMessage(), containsString(otherClusterState.metaData().clusterUUID())); |
| 177 | + } |
| 178 | + |
| 179 | + { |
| 180 | + final ClusterState otherClusterState = ClusterState.builder(ClusterName.DEFAULT).metaData(MetaData.builder() |
| 181 | + .generateClusterUuidIfNeeded()).build(); |
| 182 | + |
| 183 | + final PlainActionFuture<TransportResponse.Empty> future = new PlainActionFuture<>(); |
| 184 | + transportService.sendRequest(localNode, MembershipAction.DISCOVERY_JOIN_VALIDATE_ACTION_NAME, |
| 185 | + new ValidateJoinRequest(otherClusterState), |
| 186 | + new ActionListenerResponseHandler<>(future, in -> TransportResponse.Empty.INSTANCE)); |
| 187 | + deterministicTaskQueue.runAllTasks(); |
| 188 | + |
| 189 | + final CoordinationStateRejectedException coordinationStateRejectedException |
| 190 | + = expectThrows(CoordinationStateRejectedException.class, future::actionGet); |
| 191 | + assertThat(coordinationStateRejectedException.getMessage(), |
| 192 | + containsString("join validation on cluster state with a different cluster uuid")); |
| 193 | + assertThat(coordinationStateRejectedException.getMessage(), containsString(localClusterState.metaData().clusterUUID())); |
| 194 | + assertThat(coordinationStateRejectedException.getMessage(), containsString(otherClusterState.metaData().clusterUUID())); |
| 195 | + } |
| 196 | + } |
134 | 197 | }
|
0 commit comments