diff --git a/core/src/main/java/org/elasticsearch/cluster/ClusterChangedEvent.java b/core/src/main/java/org/elasticsearch/cluster/ClusterChangedEvent.java index 0863fbfc4f47b..e851b7814da5a 100644 --- a/core/src/main/java/org/elasticsearch/cluster/ClusterChangedEvent.java +++ b/core/src/main/java/org/elasticsearch/cluster/ClusterChangedEvent.java @@ -25,12 +25,12 @@ import org.elasticsearch.cluster.node.DiscoveryNodes; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Objects; /** - * + * An event received by the local node, signaling that the cluster state has changed. */ public class ClusterChangedEvent { @@ -43,6 +43,9 @@ public class ClusterChangedEvent { private final DiscoveryNodes.Delta nodesDelta; public ClusterChangedEvent(String source, ClusterState state, ClusterState previousState) { + Objects.requireNonNull(source, "source must not be null"); + Objects.requireNonNull(state, "state must not be null"); + Objects.requireNonNull(previousState, "previousState must not be null"); this.source = source; this.state = state; this.previousState = previousState; @@ -56,19 +59,35 @@ public String source() { return this.source; } + /** + * The new cluster state that caused this change event. + */ public ClusterState state() { return this.state; } + /** + * The previous cluster state for this change event. + */ public ClusterState previousState() { return this.previousState; } + /** + * Returns true iff the routing tables (for all indices) have + * changed between the previous cluster state and the current cluster state. + * Note that this is an object reference equality test, not an equals test. + */ public boolean routingTableChanged() { return state.routingTable() != previousState.routingTable(); } + /** + * Returns true iff the routing table has changed for the given index. + * Note that this is an object reference equality test, not an equals test. + */ public boolean indexRoutingTableChanged(String index) { + Objects.requireNonNull(index, "index must not be null"); if (!state.routingTable().hasIndex(index) && !previousState.routingTable().hasIndex(index)) { return false; } @@ -82,9 +101,6 @@ public boolean indexRoutingTableChanged(String index) { * Returns the indices created in this event */ public List indicesCreated() { - if (previousState == null) { - return Arrays.asList(state.metaData().indices().keys().toArray(String.class)); - } if (!metaDataChanged()) { return Collections.emptyList(); } @@ -105,20 +121,14 @@ public List indicesCreated() { * Returns the indices deleted in this event */ public List indicesDeleted() { - - // if the new cluster state has a new master then we cannot know if an index which is not in the cluster state - // is actually supposed to be deleted or imported as dangling instead. for example a new master might not have - // the index in its cluster state because it was started with an empty data folder and in this case we want to - // import as dangling. we check here for new master too to be on the safe side in this case. - // This means that under certain conditions deleted indices might be reimported if a master fails while the deletion - // request is issued and a node receives the cluster state that would trigger the deletion from the new master. - // See test MetaDataWriteDataNodesTests.testIndicesDeleted() + // If the new cluster state has a new cluster UUID, the likely scenario is that a node was elected + // master that has had its data directory wiped out, in which case we don't want to delete the indices and lose data; + // rather we want to import them as dangling indices instead. So we check here if the cluster UUID differs from the previous + // cluster UUID, in which case, we don't want to delete indices that the master erroneously believes shouldn't exist. + // See test DiscoveryWithServiceDisruptionsIT.testIndicesDeleted() // See discussion on https://github.com/elastic/elasticsearch/pull/9952 and // https://github.com/elastic/elasticsearch/issues/11665 - if (hasNewMaster() || previousState == null) { - return Collections.emptyList(); - } - if (!metaDataChanged()) { + if (metaDataChanged() == false || isNewCluster()) { return Collections.emptyList(); } List deleted = null; @@ -134,10 +144,20 @@ public List indicesDeleted() { return deleted == null ? Collections.emptyList() : deleted; } + /** + * Returns true iff the metadata for the cluster has changed between + * the previous cluster state and the new cluster state. Note that this is an object + * reference equality test, not an equals test. + */ public boolean metaDataChanged() { return state.metaData() != previousState.metaData(); } + /** + * Returns true iff the {@link IndexMetaData} for a given index + * has changed between the previous cluster state and the new cluster state. + * Note that this is an object reference equality test, not an equals test. + */ public boolean indexMetaDataChanged(IndexMetaData current) { MetaData previousMetaData = previousState.metaData(); if (previousMetaData == null) { @@ -152,46 +172,56 @@ public boolean indexMetaDataChanged(IndexMetaData current) { return true; } + /** + * Returns true iff the cluster level blocks have changed between cluster states. + * Note that this is an object reference equality test, not an equals test. + */ public boolean blocksChanged() { return state.blocks() != previousState.blocks(); } + /** + * Returns true iff the local node is the mater node of the cluster. + */ public boolean localNodeMaster() { return state.nodes().localNodeMaster(); } + /** + * Returns the {@link org.elasticsearch.cluster.node.DiscoveryNodes.Delta} between + * the previous cluster state and the new cluster state. + */ public DiscoveryNodes.Delta nodesDelta() { return this.nodesDelta; } + /** + * Returns true iff nodes have been removed from the cluster since the last cluster state. + */ public boolean nodesRemoved() { return nodesDelta.removed(); } + /** + * Returns true iff nodes have been added from the cluster since the last cluster state. + */ public boolean nodesAdded() { return nodesDelta.added(); } + /** + * Returns true iff nodes have been changed (added or removed) from the cluster since the last cluster state. + */ public boolean nodesChanged() { return nodesRemoved() || nodesAdded(); } - /** - * Checks if this cluster state comes from a different master than the previous one. - * This is a workaround for the scenario where a node misses a cluster state that has either - * no master block or state not recovered flag set. In this case we must make sure that - * if an index is missing from the cluster state is not deleted immediately but instead imported - * as dangling. See discussion on https://github.com/elastic/elasticsearch/pull/9952 - */ - private boolean hasNewMaster() { - String oldMaster = previousState().getNodes().masterNodeId(); - String newMaster = state().getNodes().masterNodeId(); - if (oldMaster == null && newMaster == null) { - return false; - } - if (oldMaster == null && newMaster != null) { - return true; - } - return oldMaster.equals(newMaster) == false; + // Determines whether or not the current cluster state represents an entirely + // different cluster from the previous cluster state, which will happen when a + // master node is elected that has never been part of the cluster before. + private boolean isNewCluster() { + final String prevClusterUUID = previousState.metaData().clusterUUID(); + final String currClusterUUID = state.metaData().clusterUUID(); + return prevClusterUUID.equals(currClusterUUID) == false; } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/elasticsearch/cluster/node/DiscoveryNode.java b/core/src/main/java/org/elasticsearch/cluster/node/DiscoveryNode.java index d8504a210c108..44f2f4000bd1d 100644 --- a/core/src/main/java/org/elasticsearch/cluster/node/DiscoveryNode.java +++ b/core/src/main/java/org/elasticsearch/cluster/node/DiscoveryNode.java @@ -46,6 +46,11 @@ */ public class DiscoveryNode implements Streamable, ToXContent { + public static final String DATA_ATTR = "data"; + public static final String MASTER_ATTR = "master"; + public static final String CLIENT_ATTR = "client"; + public static final String INGEST_ATTR = "ingest"; + public static boolean localNode(Settings settings) { if (Node.NODE_LOCAL_SETTING.exists(settings)) { return Node.NODE_LOCAL_SETTING.get(settings); @@ -274,7 +279,7 @@ public ImmutableOpenMap getAttributes() { * Should this node hold data (shards) or not. */ public boolean dataNode() { - String data = attributes.get("data"); + String data = attributes.get(DATA_ATTR); if (data == null) { return !clientNode(); } @@ -292,7 +297,7 @@ public boolean isDataNode() { * Is the node a client node or not. */ public boolean clientNode() { - String client = attributes.get("client"); + String client = attributes.get(CLIENT_ATTR); return client != null && Booleans.parseBooleanExact(client); } @@ -304,7 +309,7 @@ public boolean isClientNode() { * Can this node become master or not. */ public boolean masterNode() { - String master = attributes.get("master"); + String master = attributes.get(MASTER_ATTR); if (master == null) { return !clientNode(); } @@ -322,7 +327,7 @@ public boolean isMasterNode() { * Returns a boolean that tells whether this an ingest node or not */ public boolean isIngestNode() { - String ingest = attributes.get("ingest"); + String ingest = attributes.get(INGEST_ATTR); return ingest == null ? true : Booleans.parseBooleanExact(ingest); } diff --git a/core/src/test/java/org/elasticsearch/cluster/ClusterChangedEventTests.java b/core/src/test/java/org/elasticsearch/cluster/ClusterChangedEventTests.java new file mode 100644 index 0000000000000..cefd3a6703a85 --- /dev/null +++ b/core/src/test/java/org/elasticsearch/cluster/ClusterChangedEventTests.java @@ -0,0 +1,375 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.cluster; + +import com.carrotsearch.hppc.cursors.ObjectCursor; +import org.elasticsearch.Version; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.routing.RoutingTable; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.collect.MapBuilder; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.transport.DummyTransportAddress; +import org.elasticsearch.test.ESTestCase; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static org.hamcrest.Matchers.equalTo; + +/** + * Tests for the {@link ClusterChangedEvent} class. + */ +public class ClusterChangedEventTests extends ESTestCase { + + private static final ClusterName TEST_CLUSTER_NAME = new ClusterName("test"); + private static final int INDICES_CHANGE_NUM_TESTS = 5; + private static final String NODE_ID_PREFIX = "node_"; + private static final String INITIAL_CLUSTER_ID = Strings.randomBase64UUID(); + // the initial indices which every cluster state test starts out with + private static final List initialIndices = Arrays.asList("idx1", "idx2", "idx3"); + // index settings + private static final Settings settings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build(); + + /** + * Test basic properties of the ClusterChangedEvent class: + * (1) make sure there are no null values for any of its properties + * (2) make sure you can't create a ClusterChangedEvent with any null values + */ + public void testBasicProperties() { + ClusterState newState = createSimpleClusterState(); + ClusterState previousState = createSimpleClusterState(); + ClusterChangedEvent event = new ClusterChangedEvent("_na_", newState, previousState); + assertThat(event.source(), equalTo("_na_")); + assertThat(event.state(), equalTo(newState)); + assertThat(event.previousState(), equalTo(previousState)); + assertNotNull("nodesDelta should not be null", event.nodesDelta()); + + // should not be able to create a ClusterChangedEvent with null values for any of the constructor args + try { + event = new ClusterChangedEvent(null, newState, previousState); + fail("should not have created a ClusterChangedEvent from a null source: " + event.source()); + } catch (NullPointerException e) { + } + try { + event = new ClusterChangedEvent("_na_", null, previousState); + fail("should not have created a ClusterChangedEvent from a null state: " + event.state()); + } catch (NullPointerException e) { + } + try { + event = new ClusterChangedEvent("_na_", newState, null); + fail("should not have created a ClusterChangedEvent from a null previousState: " + event.previousState()); + } catch (NullPointerException e) { + } + } + + /** + * Test whether the ClusterChangedEvent returns the correct value for whether the local node is master, + * based on what was set on the cluster state. + */ + public void testLocalNodeIsMaster() { + final int numNodesInCluster = 3; + ClusterState previousState = createSimpleClusterState(); + ClusterState newState = createState(numNodesInCluster, true, initialIndices); + ClusterChangedEvent event = new ClusterChangedEvent("_na_", newState, previousState); + assertTrue("local node should be master", event.localNodeMaster()); + + newState = createState(numNodesInCluster, false, initialIndices); + event = new ClusterChangedEvent("_na_", newState, previousState); + assertFalse("local node should not be master", event.localNodeMaster()); + } + + /** + * Test that the indices created and indices deleted lists between two cluster states + * are correct when there is no change in the cluster UUID. Also tests metadata equality + * between cluster states. + */ + public void testMetaDataChangesOnNoMasterChange() { + metaDataChangesCheck(false); + } + + /** + * Test that the indices created and indices deleted lists between two cluster states + * are correct when there is a change in the cluster UUID. Also tests metadata equality + * between cluster states. + */ + public void testMetaDataChangesOnNewClusterUUID() { + metaDataChangesCheck(true); + } + + /** + * Test the index metadata change check. + */ + public void testIndexMetaDataChange() { + final int numNodesInCluster = 3; + final ClusterState originalState = createState(numNodesInCluster, randomBoolean(), initialIndices); + final ClusterState newState = originalState; // doesn't matter for this test, just need a non-null value + final ClusterChangedEvent event = new ClusterChangedEvent("_na_", originalState, newState); + + // test when its not the same IndexMetaData + final String indexId = initialIndices.get(0); + final IndexMetaData originalIndexMeta = originalState.metaData().index(indexId); + // make sure the metadata is actually on the cluster state + assertNotNull("IndexMetaData for " + indexId + " should exist on the cluster state", originalIndexMeta); + IndexMetaData newIndexMeta = createIndexMetadata(indexId, originalIndexMeta.getVersion() + 1); + assertTrue("IndexMetaData with different version numbers must be considered changed", event.indexMetaDataChanged(newIndexMeta)); + + // test when it doesn't exist + newIndexMeta = createIndexMetadata("doesntexist"); + assertTrue("IndexMetaData that didn't previously exist should be considered changed", event.indexMetaDataChanged(newIndexMeta)); + + // test when its the same IndexMetaData + assertFalse("IndexMetaData should be the same", event.indexMetaDataChanged(originalIndexMeta)); + } + + /** + * Test nodes added/removed/changed checks. + */ + public void testNodesAddedAndRemovedAndChanged() { + final int numNodesInCluster = 4; + final ClusterState originalState = createState(numNodesInCluster, randomBoolean(), initialIndices); + + // test when nodes have not been added or removed between cluster states + ClusterState newState = createState(numNodesInCluster, randomBoolean(), initialIndices); + ClusterChangedEvent event = new ClusterChangedEvent("_na_", newState, originalState); + assertFalse("Nodes should not have been added between cluster states", event.nodesAdded()); + assertFalse("Nodes should not have been removed between cluster states", event.nodesRemoved()); + assertFalse("Nodes should not have been changed between cluster states", event.nodesChanged()); + + // test when nodes have been removed between cluster states + newState = createState(numNodesInCluster - 1, randomBoolean(), initialIndices); + event = new ClusterChangedEvent("_na_", newState, originalState); + assertTrue("Nodes should have been removed between cluster states", event.nodesRemoved()); + assertFalse("Nodes should not have been added between cluster states", event.nodesAdded()); + assertTrue("Nodes should have been changed between cluster states", event.nodesChanged()); + + // test when nodes have been added between cluster states + newState = createState(numNodesInCluster + 1, randomBoolean(), initialIndices); + event = new ClusterChangedEvent("_na_", newState, originalState); + assertFalse("Nodes should not have been removed between cluster states", event.nodesRemoved()); + assertTrue("Nodes should have been added between cluster states", event.nodesAdded()); + assertTrue("Nodes should have been changed between cluster states", event.nodesChanged()); + + // test when nodes both added and removed between cluster states + // here we reuse the newState from the previous run which already added extra nodes + newState = nextState(newState, randomBoolean(), Collections.emptyList(), Collections.emptyList(), 1); + event = new ClusterChangedEvent("_na_", newState, originalState); + assertTrue("Nodes should have been removed between cluster states", event.nodesRemoved()); + assertTrue("Nodes should have been added between cluster states", event.nodesAdded()); + assertTrue("Nodes should have been changed between cluster states", event.nodesChanged()); + } + + /** + * Test the routing table changes checks. + */ + public void testRoutingTableChanges() { + final int numNodesInCluster = 3; + final ClusterState originalState = createState(numNodesInCluster, randomBoolean(), initialIndices); + + // routing tables and index routing tables are same object + ClusterState newState = ClusterState.builder(originalState).build(); + ClusterChangedEvent event = new ClusterChangedEvent("_na_", originalState, newState); + assertFalse("routing tables should be the same object", event.routingTableChanged()); + assertFalse("index routing table should be the same object", event.indexRoutingTableChanged(initialIndices.get(0))); + + // routing tables and index routing tables aren't same object + newState = createState(numNodesInCluster, randomBoolean(), initialIndices); + event = new ClusterChangedEvent("_na_", originalState, newState); + assertTrue("routing tables should not be the same object", event.routingTableChanged()); + assertTrue("index routing table should not be the same object", event.indexRoutingTableChanged(initialIndices.get(0))); + + // index routing tables are different because they don't exist + newState = createState(numNodesInCluster, randomBoolean(), initialIndices.subList(1, initialIndices.size())); + event = new ClusterChangedEvent("_na_", originalState, newState); + assertTrue("routing tables should not be the same object", event.routingTableChanged()); + assertTrue("index routing table should not be the same object", event.indexRoutingTableChanged(initialIndices.get(0))); + } + + // Tests that the indices change list is correct as well as metadata equality when the metadata has changed. + private static void metaDataChangesCheck(final boolean changeClusterUUID) { + final int numNodesInCluster = 3; + for (int i = 0; i < INDICES_CHANGE_NUM_TESTS; i++) { + final ClusterState previousState = createState(numNodesInCluster, randomBoolean(), initialIndices); + final int numAdd = randomIntBetween(0, 5); // add random # of indices to the next cluster state + final int numDel = randomIntBetween(0, initialIndices.size()); // delete random # of indices from the next cluster state + final List addedIndices = addIndices(numAdd); + final List delIndices = delIndices(numDel, initialIndices); + final ClusterState newState = nextState(previousState, changeClusterUUID, addedIndices, delIndices, 0); + final ClusterChangedEvent event = new ClusterChangedEvent("_na_", newState, previousState); + final List addsFromEvent = event.indicesCreated(); + final List delsFromEvent = event.indicesDeleted(); + Collections.sort(addsFromEvent); + Collections.sort(delsFromEvent); + assertThat(addsFromEvent, equalTo(addedIndices)); + assertThat(delsFromEvent, changeClusterUUID ? equalTo(Collections.emptyList()) : equalTo(delIndices)); + assertThat(event.metaDataChanged(), equalTo(changeClusterUUID || addedIndices.size() > 0 || delIndices.size() > 0)); + } + } + + private static ClusterState createSimpleClusterState() { + return ClusterState.builder(TEST_CLUSTER_NAME).build(); + } + + // Create a basic cluster state with a given set of indices + private static ClusterState createState(final int numNodes, final boolean isLocalMaster, final List indices) { + final MetaData metaData = createMetaData(indices); + return ClusterState.builder(TEST_CLUSTER_NAME) + .nodes(createDiscoveryNodes(numNodes, isLocalMaster)) + .metaData(metaData) + .routingTable(createRoutingTable(1, metaData)) + .build(); + } + + // Create a modified cluster state from another one, but with some number of indices added and deleted. + private static ClusterState nextState(final ClusterState previousState, final boolean changeClusterUUID, + final List addedIndices, final List deletedIndices, + final int numNodesToRemove) { + final ClusterState.Builder builder = ClusterState.builder(previousState); + builder.stateUUID(Strings.randomBase64UUID()); + final MetaData.Builder metaBuilder = MetaData.builder(previousState.metaData()); + if (changeClusterUUID || addedIndices.size() > 0 || deletedIndices.size() > 0) { + // there is some change in metadata cluster state + if (changeClusterUUID) { + metaBuilder.clusterUUID(Strings.randomBase64UUID()); + } + for (String index : addedIndices) { + metaBuilder.put(createIndexMetadata(index), true); + } + for (String index : deletedIndices) { + metaBuilder.remove(index); + } + builder.metaData(metaBuilder); + } + if (numNodesToRemove > 0) { + final int discoveryNodesSize = previousState.getNodes().size(); + final DiscoveryNodes.Builder nodesBuilder = DiscoveryNodes.builder(previousState.getNodes()); + for (int i = 0; i < numNodesToRemove && i < discoveryNodesSize; i++) { + nodesBuilder.remove(NODE_ID_PREFIX + i); + } + builder.nodes(nodesBuilder); + } + return builder.build(); + } + + // Create the discovery nodes for a cluster state. For our testing purposes, we want + // the first to be master, the second to be master eligible, the third to be a data node, + // and the remainder can be any kinds of nodes (master eligible, data, or both). + private static DiscoveryNodes createDiscoveryNodes(final int numNodes, final boolean isLocalMaster) { + assert (numNodes >= 3) : "the initial cluster state for event change tests should have a minimum of 3 nodes " + + "so there are a minimum of 2 master nodes for testing master change events."; + final DiscoveryNodes.Builder builder = DiscoveryNodes.builder(); + final int localNodeIndex = isLocalMaster ? 0 : randomIntBetween(1, numNodes - 1); // randomly assign the local node if not master + for (int i = 0; i < numNodes; i++) { + final String nodeId = NODE_ID_PREFIX + i; + boolean isMasterEligible = false; + boolean isData = false; + if (i == 0) { + // the master node + builder.masterNodeId(nodeId); + isMasterEligible = true; + } else if (i == 1) { + // the alternate master node + isMasterEligible = true; + } else if (i == 2) { + // we need at least one data node + isData = true; + } else { + // remaining nodes can be anything (except for master) + isMasterEligible = randomBoolean(); + isData = randomBoolean(); + } + final DiscoveryNode node = newNode(nodeId, isMasterEligible, isData); + builder.put(node); + if (i == localNodeIndex) { + builder.localNodeId(nodeId); + } + } + return builder.build(); + } + + // Create a new DiscoveryNode + private static DiscoveryNode newNode(final String nodeId, boolean isMasterEligible, boolean isData) { + final Map attributes = MapBuilder.newMapBuilder() + .put(DiscoveryNode.MASTER_ATTR, isMasterEligible ? "true" : "false") + .put(DiscoveryNode.DATA_ATTR, isData ? "true": "false") + .immutableMap(); + return new DiscoveryNode(nodeId, nodeId, DummyTransportAddress.INSTANCE, attributes, Version.CURRENT); + } + + // Create the metadata for a cluster state. + private static MetaData createMetaData(final List indices) { + final MetaData.Builder builder = MetaData.builder(); + builder.clusterUUID(INITIAL_CLUSTER_ID); + for (String index : indices) { + builder.put(createIndexMetadata(index), true); + } + return builder.build(); + } + + // Create the index metadata for a given index. + private static IndexMetaData createIndexMetadata(final String index) { + return createIndexMetadata(index, 1); + } + + // Create the index metadata for a given index, with the specified version. + private static IndexMetaData createIndexMetadata(final String index, final long version) { + return IndexMetaData.builder(index) + .settings(settings) + .numberOfShards(1) + .numberOfReplicas(0) + .creationDate(System.currentTimeMillis()) + .version(version) + .build(); + } + + // Create the routing table for a cluster state. + private static RoutingTable createRoutingTable(final long version, final MetaData metaData) { + final RoutingTable.Builder builder = RoutingTable.builder().version(version); + for (ObjectCursor cursor : metaData.indices().values()) { + builder.addAsNew(cursor.value); + } + return builder.build(); + } + + // Create a list of indices to add + private static List addIndices(final int numIndices) { + final List list = new ArrayList<>(); + for (int i = 0; i < numIndices; i++) { + list.add("newIdx_" + i); + } + return list; + } + + // Create a list of indices to delete from a list that already belongs to a particular cluster state. + private static List delIndices(final int numIndices, final List currIndices) { + final List list = new ArrayList<>(); + for (int i = 0; i < numIndices; i++) { + list.add(currIndices.get(i)); + } + return list; + } + +} diff --git a/core/src/test/java/org/elasticsearch/discovery/DiscoveryWithServiceDisruptionsIT.java b/core/src/test/java/org/elasticsearch/discovery/DiscoveryWithServiceDisruptionsIT.java index 8c7da89fd8fff..6caf0846344fb 100644 --- a/core/src/test/java/org/elasticsearch/discovery/DiscoveryWithServiceDisruptionsIT.java +++ b/core/src/test/java/org/elasticsearch/discovery/DiscoveryWithServiceDisruptionsIT.java @@ -581,8 +581,7 @@ public void testMasterNodeGCs() throws Exception { // restore GC masterNodeDisruption.stopDisrupting(); - ensureStableCluster(3, new TimeValue(DISRUPTION_HEALING_OVERHEAD.millis() + masterNodeDisruption.expectedTimeToHeal().millis()), false, - oldNonMasterNodes.get(0)); + ensureStableCluster(3, new TimeValue(DISRUPTION_HEALING_OVERHEAD.millis() + masterNodeDisruption.expectedTimeToHeal().millis()), false, oldNonMasterNodes.get(0)); // make sure all nodes agree on master String newMaster = internalCluster().getMasterName(); @@ -1072,11 +1071,13 @@ public boolean clearData(String nodeName) { assertTrue(client().prepareGet("index", "doc", "1").get().isExists()); } - // tests if indices are really deleted even if a master transition inbetween - @AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/11665") + /** + * Tests that indices are properly deleted even if there is a master transition in between. + * Test for https://github.com/elastic/elasticsearch/issues/11665 + */ public void testIndicesDeleted() throws Exception { configureUnicastCluster(3, null, 2); - InternalTestCluster.Async> masterNodes= internalCluster().startMasterOnlyNodesAsync(2); + InternalTestCluster.Async> masterNodes = internalCluster().startMasterOnlyNodesAsync(2); InternalTestCluster.Async dataNode = internalCluster().startDataOnlyNodeAsync(); dataNode.get(); masterNodes.get();