From 12c421adc058f0b5527322bc63147d965986f28e Mon Sep 17 00:00:00 2001 From: Niels Bauman Date: Sat, 6 Sep 2025 08:28:08 -0300 Subject: [PATCH 1/2] Clean up `SearchableSnapshotActionIT` As a follow-up of #133954, this class could use a clean up in deduplicating code, replacing some `assertBusy`s with `awaitIndexExists`, and more. --- .../xpack/TimeSeriesRestDriver.java | 49 ++- .../actions/SearchableSnapshotActionIT.java | 296 +++++------------- 2 files changed, 91 insertions(+), 254 deletions(-) diff --git a/x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/TimeSeriesRestDriver.java b/x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/TimeSeriesRestDriver.java index 299b9e9313b89..e943d6c69aeed 100644 --- a/x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/TimeSeriesRestDriver.java +++ b/x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/TimeSeriesRestDriver.java @@ -50,6 +50,7 @@ import java.util.concurrent.TimeUnit; import static org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_NUMBER_OF_SHARDS; +import static org.elasticsearch.test.ESTestCase.assertThat; import static org.elasticsearch.test.ESTestCase.randomAlphaOfLengthBetween; import static org.elasticsearch.test.ESTestCase.randomBoolean; import static org.elasticsearch.test.ESTestCase.waitUntil; @@ -59,8 +60,6 @@ import static org.elasticsearch.xpack.core.ilm.ShrinkIndexNameSupplier.SHRUNKEN_INDEX_PREFIX; import static org.hamcrest.Matchers.anyOf; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; /** * This class provides the operational REST functions needed to control an ILM time series lifecycle. @@ -80,7 +79,7 @@ public static Step.StepKey getStepKeyForIndex(RestClient client, String indexNam return getStepKey(indexResponse); } - private static Step.StepKey getStepKey(Map explainIndexResponse) { + public static Step.StepKey getStepKey(Map explainIndexResponse) { String phase = (String) explainIndexResponse.get("phase"); String action = (String) explainIndexResponse.get("action"); String step = (String) explainIndexResponse.get("step"); @@ -105,14 +104,26 @@ public static Map> explain(RestClient client, String explainRequest.addParameter("only_managed", Boolean.toString(onlyManaged)); explainRequest.setOptions(consumeWarningsOptions); Response response = client.performRequest(explainRequest); - Map responseMap; - try (InputStream is = response.getEntity().getContent()) { - responseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), is, true); - } + ObjectPath objectPath = ObjectPath.createFromResponse(response); + return objectPath.evaluate("indices"); + } - @SuppressWarnings("unchecked") - Map> indexResponse = ((Map>) responseMap.get("indices")); - return indexResponse; + /** + * Waits until the specified index is at the specified ILM step. If any of phase, action, or step is null, that part is ignored. + */ + public static void awaitStepKey(RestClient client, String indexName, String phase, String action, String step) throws Exception { + ESRestTestCase.assertBusy(() -> { + final Step.StepKey stepKey = getStepKeyForIndex(client, indexName); + if (phase != null) { + assertThat(stepKey.phase(), equalTo(phase)); + } + if (action != null) { + assertThat(stepKey.action(), equalTo(action)); + } + if (step != null) { + assertThat(stepKey.name(), equalTo(step)); + } + }); } public static void indexDocument(RestClient client, String indexAbstractionName) throws IOException { @@ -501,24 +512,6 @@ public static String waitAndGetShrinkIndexName(RestClient client, String origina return shrunkenIndexName[0]; } - @SuppressWarnings("unchecked") - public static List getBackingIndices(RestClient client, String dataStreamName) throws IOException { - Response getDataStream = client.performRequest(new Request("GET", "_data_stream/" + dataStreamName)); - Map responseMap; - try (InputStream is = getDataStream.getEntity().getContent()) { - responseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), is, true); - } - - List> dataStreams = (List>) responseMap.get("data_streams"); - assertThat(dataStreams.size(), is(1)); - Map dataStream = dataStreams.get(0); - assertThat(dataStream.get("name"), is(dataStreamName)); - List indices = ((List>) dataStream.get("indices")).stream() - .map(indexMap -> (String) indexMap.get("index_name")) - .toList(); - return indices; - } - private static void executeDummyClusterStateUpdate(RestClient client) throws IOException { createIndexWithSettings( client, diff --git a/x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/ilm/actions/SearchableSnapshotActionIT.java b/x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/ilm/actions/SearchableSnapshotActionIT.java index 111de0b6f400a..478516030cca6 100644 --- a/x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/ilm/actions/SearchableSnapshotActionIT.java +++ b/x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/ilm/actions/SearchableSnapshotActionIT.java @@ -19,12 +19,10 @@ import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider; import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.core.TimeValue; import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.test.rest.ObjectPath; import org.elasticsearch.xcontent.XContentBuilder; -import org.elasticsearch.xcontent.XContentType; import org.elasticsearch.xpack.TimeSeriesRestDriver; import org.elasticsearch.xpack.core.ilm.AllocateAction; import org.elasticsearch.xpack.core.ilm.DeleteAction; @@ -44,7 +42,6 @@ import org.junit.Before; import java.io.IOException; -import java.io.InputStream; import java.util.HashMap; import java.util.List; import java.util.Locale; @@ -113,19 +110,11 @@ public void testSearchableSnapshotAction() throws Exception { assertThat(backingIndices.size(), equalTo(2)); String backingIndexName = backingIndices.getFirst(); String restoredIndexName = SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + backingIndexName; - assertTrue(waitUntil(() -> { - try { - return indexExists(restoredIndexName); - } catch (IOException e) { - return false; - } - }, 30, TimeUnit.SECONDS)); + awaitIndexExists(restoredIndexName); - assertBusy( - () -> { assertThat(explainIndex(client(), restoredIndexName).get("step"), is(PhaseCompleteStep.NAME)); }, - 30, - TimeUnit.SECONDS - ); + TimeSeriesRestDriver.awaitStepKey(client(), restoredIndexName, null, null, PhaseCompleteStep.NAME); + // Wait for the original index to be deleted, to ensure ILM has finished + awaitIndexDoesNotExist(backingIndexName); } /** @@ -218,7 +207,6 @@ public void testSearchableSnapshotForceMergesClonedIndexAfterRetry() throws Exce } } - @SuppressWarnings("unchecked") public void testDeleteActionDeletesSearchableSnapshot() throws Exception { createSnapshotRepo(client(), snapshotRepo, randomBoolean()); @@ -254,25 +242,15 @@ public void testDeleteActionDeletesSearchableSnapshot() throws Exception { String restoredIndexName = SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + backingIndexName; // let's wait for ILM to finish - assertBusy(() -> assertFalse(indexExists(backingIndexName)), 60, TimeUnit.SECONDS); - assertBusy(() -> assertFalse(indexExists(restoredIndexName)), 60, TimeUnit.SECONDS); + awaitIndexDoesNotExist(backingIndexName); + awaitIndexDoesNotExist(restoredIndexName); - assertTrue("the snapshot we generate in the cold phase should be deleted by the delete phase", waitUntil(() -> { - try { - Request getSnapshotsRequest = new Request("GET", "_snapshot/" + snapshotRepo + "/_all"); - Response getSnapshotsResponse = client().performRequest(getSnapshotsRequest); - - Map responseMap; - try (InputStream is = getSnapshotsResponse.getEntity().getContent()) { - responseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), is, true); - } - Object snapshots = responseMap.get("snapshots"); - return ((List>) snapshots).size() == 0; - } catch (Exception e) { - logger.error(e.getMessage(), e); - return false; - } - }, 30, TimeUnit.SECONDS)); + List> snapshots = getSnapshots(); + assertThat( + "the snapshot we generate in the cold phase should be deleted by the delete phase, but got snapshot: " + snapshots, + snapshots.size(), + equalTo(0) + ); } public void testCreateInvalidPolicy() { @@ -344,19 +322,8 @@ public void testUpdatePolicyToAddPhasesYieldsInvalidActionsToBeSkipped() throws String backingIndexName = getDataStreamBackingIndexNames(dataStream).getFirst(); String restoredIndexName = SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + backingIndexName; - assertTrue(waitUntil(() -> { - try { - return indexExists(restoredIndexName); - } catch (IOException e) { - return false; - } - }, 30, TimeUnit.SECONDS)); - - assertBusy(() -> { - Step.StepKey stepKeyForIndex = getStepKeyForIndex(client(), restoredIndexName); - assertThat(stepKeyForIndex.phase(), is("hot")); - assertThat(stepKeyForIndex.name(), is(PhaseCompleteStep.NAME)); - }, 30, TimeUnit.SECONDS); + awaitIndexExists(restoredIndexName); + TimeSeriesRestDriver.awaitStepKey(client(), restoredIndexName, "hot", null, PhaseCompleteStep.NAME); // Wait for the original index to be deleted, to ensure ILM has finished awaitIndexDoesNotExist(backingIndexName); @@ -376,11 +343,7 @@ public void testUpdatePolicyToAddPhasesYieldsInvalidActionsToBeSkipped() throws // even though the index is now mounted as a searchable snapshot, the actions that can't operate on it should // skip and ILM should not be blocked (not should the managed index move into the ERROR step) - assertBusy(() -> { - Step.StepKey stepKeyForIndex = getStepKeyForIndex(client(), restoredIndexName); - assertThat(stepKeyForIndex.phase(), is("cold")); - assertThat(stepKeyForIndex.name(), is(PhaseCompleteStep.NAME)); - }, 30, TimeUnit.SECONDS); + TimeSeriesRestDriver.awaitStepKey(client(), restoredIndexName, "cold", null, PhaseCompleteStep.NAME); } public void testRestoredIndexManagedByLocalPolicySkipsIllegalActions() throws Exception { @@ -423,19 +386,8 @@ public void testRestoredIndexManagedByLocalPolicySkipsIllegalActions() throws Ex String backingIndexName = getDataStreamBackingIndexNames(dataStream).getFirst(); String searchableSnapMountedIndexName = SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + backingIndexName; - assertTrue(waitUntil(() -> { - try { - return indexExists(searchableSnapMountedIndexName); - } catch (IOException e) { - return false; - } - }, 30, TimeUnit.SECONDS)); - - assertBusy(() -> { - Step.StepKey stepKeyForIndex = getStepKeyForIndex(client(), searchableSnapMountedIndexName); - assertThat(stepKeyForIndex.phase(), is("hot")); - assertThat(stepKeyForIndex.name(), is(PhaseCompleteStep.NAME)); - }, 30, TimeUnit.SECONDS); + awaitIndexExists(searchableSnapMountedIndexName); + TimeSeriesRestDriver.awaitStepKey(client(), searchableSnapMountedIndexName, "hot", null, PhaseCompleteStep.NAME); // Wait for the original index to be deleted, to ensure ILM has finished awaitIndexDoesNotExist(backingIndexName); @@ -489,14 +441,15 @@ public void testRestoredIndexManagedByLocalPolicySkipsIllegalActions() throws Ex e.getMessage(), containsString("The freeze action in ILM is deprecated and will be removed in a future version") ); - stepKeyForIndex = getKeyForIndex(e.getResponse(), searchableSnapMountedIndexName); + ObjectPath objectPath = ObjectPath.createFromResponse(e.getResponse()); + Map> indices = objectPath.evaluate("indices"); + stepKeyForIndex = TimeSeriesRestDriver.getStepKey(indices.get(searchableSnapMountedIndexName)); } assertThat(stepKeyForIndex.phase(), is("cold")); assertThat(stepKeyForIndex.name(), is(PhaseCompleteStep.NAME)); }, 30, TimeUnit.SECONDS); } - @SuppressWarnings("unchecked") public void testIdenticalSearchableSnapshotActionIsNoop() throws Exception { String index = "myindex-" + randomAlphaOfLength(4).toLowerCase(Locale.ROOT) + "-000001"; createSnapshotRepo(client(), snapshotRepo, randomBoolean()); @@ -532,37 +485,20 @@ public void testIdenticalSearchableSnapshotActionIsNoop() throws Exception { final String searchableSnapMountedIndexName = SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + index; - assertBusy(() -> { - logger.info("--> waiting for [{}] to exist...", searchableSnapMountedIndexName); - assertTrue(indexExists(searchableSnapMountedIndexName)); - }, 30, TimeUnit.SECONDS); - - assertBusy(() -> { - Step.StepKey stepKeyForIndex = getStepKeyForIndex(client(), searchableSnapMountedIndexName); - assertThat(stepKeyForIndex.phase(), is("cold")); - assertThat(stepKeyForIndex.name(), is(PhaseCompleteStep.NAME)); - }, 30, TimeUnit.SECONDS); + logger.info("--> waiting for [{}] to exist...", searchableSnapMountedIndexName); + awaitIndexExists(searchableSnapMountedIndexName); + TimeSeriesRestDriver.awaitStepKey(client(), searchableSnapMountedIndexName, "cold", null, PhaseCompleteStep.NAME); // Wait for the original index to be deleted, to ensure ILM has finished awaitIndexDoesNotExist(index); - Request getSnaps = new Request("GET", "/_snapshot/" + snapshotRepo + "/_all"); - Response response = client().performRequest(getSnaps); - Map responseMap; - try (InputStream is = response.getEntity().getContent()) { - responseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), is, true); - } - assertThat( - "expected to have only one snapshot, but got: " + responseMap, - ((List>) responseMap.get("snapshots")).size(), - equalTo(1) - ); + List> snapshots = getSnapshots(); + assertThat("expected to have only one snapshot, but got: " + snapshots, snapshots.size(), equalTo(1)); Request hitCount = new Request("GET", "/" + searchableSnapMountedIndexName + "/_count"); Map count = entityAsMap(client().performRequest(hitCount)); assertThat("expected a single document but got: " + count, (int) count.get("count"), equalTo(1)); } - @SuppressWarnings("unchecked") public void testConvertingSearchableSnapshotFromFullToPartial() throws Exception { String index = "myindex-" + randomAlphaOfLength(4).toLowerCase(Locale.ROOT); createSnapshotRepo(client(), snapshotRepo, randomBoolean()); @@ -595,30 +531,14 @@ public void testConvertingSearchableSnapshotFromFullToPartial() throws Exception final String searchableSnapMountedIndexName = SearchableSnapshotAction.PARTIAL_RESTORED_INDEX_PREFIX + SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + index; - assertBusy(() -> { - logger.info("--> waiting for [{}] to exist...", searchableSnapMountedIndexName); - assertTrue(indexExists(searchableSnapMountedIndexName)); - }, 30, TimeUnit.SECONDS); - - assertBusy(() -> { - Step.StepKey stepKeyForIndex = getStepKeyForIndex(client(), searchableSnapMountedIndexName); - assertThat(stepKeyForIndex.phase(), is("frozen")); - assertThat(stepKeyForIndex.name(), is(PhaseCompleteStep.NAME)); - }, 30, TimeUnit.SECONDS); + logger.info("--> waiting for [{}] to exist...", searchableSnapMountedIndexName); + awaitIndexExists(searchableSnapMountedIndexName); + TimeSeriesRestDriver.awaitStepKey(client(), searchableSnapMountedIndexName, "frozen", null, PhaseCompleteStep.NAME); // Wait for the original index to be deleted, to ensure ILM has finished awaitIndexDoesNotExist(index); - Request getSnaps = new Request("GET", "/_snapshot/" + snapshotRepo + "/_all"); - Response response = client().performRequest(getSnaps); - Map responseMap; - try (InputStream is = response.getEntity().getContent()) { - responseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), is, true); - } - assertThat( - "expected to have only one snapshot, but got: " + responseMap, - ((List>) responseMap.get("snapshots")).size(), - equalTo(1) - ); + List> snapshots = getSnapshots(); + assertThat("expected to have only one snapshot, but got: " + snapshots, snapshots.size(), equalTo(1)); Request hitCount = new Request("GET", "/" + searchableSnapMountedIndexName + "/_count"); Map count = entityAsMap(client().performRequest(hitCount)); @@ -632,7 +552,6 @@ public void testConvertingSearchableSnapshotFromFullToPartial() throws Exception ); } - @SuppressWarnings("unchecked") public void testResumingSearchableSnapshotFromFullToPartial() throws Exception { String index = "myindex-" + randomAlphaOfLength(4).toLowerCase(Locale.ROOT); createSnapshotRepo(client(), snapshotRepo, randomBoolean()); @@ -678,17 +597,11 @@ public void testResumingSearchableSnapshotFromFullToPartial() throws Exception { updateIndexSettings(index, Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policyCold)); final String fullMountedIndexName = SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + index; - - assertBusy(() -> { - logger.info("--> waiting for [{}] to exist...", fullMountedIndexName); - assertTrue(indexExists(fullMountedIndexName)); - }, 30, TimeUnit.SECONDS); - - assertBusy(() -> { - Step.StepKey stepKeyForIndex = getStepKeyForIndex(client(), fullMountedIndexName); - assertThat(stepKeyForIndex.phase(), is("cold")); - assertThat(stepKeyForIndex.name(), is(PhaseCompleteStep.NAME)); - }, 30, TimeUnit.SECONDS); + logger.info("--> waiting for [{}] to exist...", fullMountedIndexName); + awaitIndexExists(fullMountedIndexName); + TimeSeriesRestDriver.awaitStepKey(client(), fullMountedIndexName, "cold", null, PhaseCompleteStep.NAME); + // Wait for the original index to be deleted, to ensure ILM has finished + awaitIndexDoesNotExist(index); // remove ILM { @@ -698,17 +611,11 @@ public void testResumingSearchableSnapshotFromFullToPartial() throws Exception { } // add cold-frozen updateIndexSettings(index, Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policyFrozen)); - String partiallyMountedIndexName = SearchableSnapshotAction.PARTIAL_RESTORED_INDEX_PREFIX + fullMountedIndexName; - assertBusy(() -> { - logger.info("--> waiting for [{}] to exist...", partiallyMountedIndexName); - assertTrue(indexExists(partiallyMountedIndexName)); - }, 30, TimeUnit.SECONDS); - assertBusy(() -> { - Step.StepKey stepKeyForIndex = getStepKeyForIndex(client(), partiallyMountedIndexName); - assertThat(stepKeyForIndex.phase(), is("frozen")); - assertThat(stepKeyForIndex.name(), is(PhaseCompleteStep.NAME)); - }, 30, TimeUnit.SECONDS); + String partiallyMountedIndexName = SearchableSnapshotAction.PARTIAL_RESTORED_INDEX_PREFIX + fullMountedIndexName; + logger.info("--> waiting for [{}] to exist...", partiallyMountedIndexName); + awaitIndexExists(partiallyMountedIndexName); + TimeSeriesRestDriver.awaitStepKey(client(), partiallyMountedIndexName, "frozen", null, PhaseCompleteStep.NAME); // Ensure the searchable snapshot is not deleted when the index was deleted because it was not created by this // policy. We add the delete phase now to ensure that the index will not be deleted before we verify the above @@ -730,16 +637,12 @@ public void testResumingSearchableSnapshotFromFullToPartial() throws Exception { ), new Phase("delete", TimeValue.ZERO, Map.of(DeleteAction.NAME, WITH_SNAPSHOT_DELETE)) ); - assertBusy(() -> { - logger.info("--> waiting for [{}] to be deleted...", partiallyMountedIndexName); - assertThat(indexExists(partiallyMountedIndexName), is(false)); - Request getSnaps = new Request("GET", "/_snapshot/" + snapshotRepo + "/_all"); - Map responseMap = responseAsMap(client().performRequest(getSnaps)); - assertThat(((List>) responseMap.get("snapshots")).size(), equalTo(1)); - }, 30, TimeUnit.SECONDS); + logger.info("--> waiting for [{}] to be deleted...", partiallyMountedIndexName); + awaitIndexDoesNotExist(partiallyMountedIndexName); + List> snapshots = getSnapshots(); + assertThat("expected to have only one snapshot, but got: " + snapshots, snapshots.size(), equalTo(1)); } - @SuppressWarnings("unchecked") public void testResumingSearchableSnapshotFromPartialToFull() throws Exception { String index = "myindex-" + randomAlphaOfLength(4).toLowerCase(Locale.ROOT); createSnapshotRepo(client(), snapshotRepo, randomBoolean()); @@ -761,7 +664,6 @@ public void testResumingSearchableSnapshotFromPartialToFull() throws Exception { createPolicy( client(), policyColdFrozen, - null, null, new Phase( @@ -787,17 +689,12 @@ public void testResumingSearchableSnapshotFromPartialToFull() throws Exception { final String fullMountedIndexName = SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + index; final String partialMountedIndexName = SearchableSnapshotAction.PARTIAL_RESTORED_INDEX_PREFIX + fullMountedIndexName; + logger.info("--> waiting for [{}] to exist...", partialMountedIndexName); + awaitIndexExists(partialMountedIndexName); + TimeSeriesRestDriver.awaitStepKey(client(), partialMountedIndexName, "frozen", null, PhaseCompleteStep.NAME); + // Wait for the original index to be deleted, to ensure ILM has finished + awaitIndexDoesNotExist(index); - assertBusy(() -> { - logger.info("--> waiting for [{}] to exist...", partialMountedIndexName); - assertTrue(indexExists(partialMountedIndexName)); - }, 30, TimeUnit.SECONDS); - - assertBusy(() -> { - Step.StepKey stepKeyForIndex = getStepKeyForIndex(client(), partialMountedIndexName); - assertThat(stepKeyForIndex.phase(), is("frozen")); - assertThat(stepKeyForIndex.name(), is(PhaseCompleteStep.NAME)); - }, 30, TimeUnit.SECONDS); // remove ILM from the partially mounted searchable snapshot { @@ -807,17 +704,11 @@ public void testResumingSearchableSnapshotFromPartialToFull() throws Exception { } // add a policy that will only include the fully mounted searchable snapshot updateIndexSettings(index, Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policyCold)); - String restoredPartiallyMountedIndexName = SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + partialMountedIndexName; - assertBusy(() -> { - logger.info("--> waiting for [{}] to exist...", restoredPartiallyMountedIndexName); - assertTrue(indexExists(restoredPartiallyMountedIndexName)); - }, 30, TimeUnit.SECONDS); - assertBusy(() -> { - Step.StepKey stepKeyForIndex = getStepKeyForIndex(client(), restoredPartiallyMountedIndexName); - assertThat(stepKeyForIndex.phase(), is("cold")); - assertThat(stepKeyForIndex.name(), is(PhaseCompleteStep.NAME)); - }, 30, TimeUnit.SECONDS); + String restoredPartiallyMountedIndexName = SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + partialMountedIndexName; + logger.info("--> waiting for [{}] to exist...", restoredPartiallyMountedIndexName); + awaitIndexExists(restoredPartiallyMountedIndexName); + TimeSeriesRestDriver.awaitStepKey(client(), restoredPartiallyMountedIndexName, "cold", null, PhaseCompleteStep.NAME); // Ensure the searchable snapshot is not deleted when the index was deleted because it was not created by this // policy. We add the delete phase now to ensure that the index will not be deleted before we verify the above @@ -835,13 +726,10 @@ public void testResumingSearchableSnapshotFromPartialToFull() throws Exception { null, new Phase("delete", TimeValue.ZERO, Map.of(DeleteAction.NAME, WITH_SNAPSHOT_DELETE)) ); - assertBusy(() -> { - logger.info("--> waiting for [{}] to be deleted...", restoredPartiallyMountedIndexName); - assertThat(indexExists(restoredPartiallyMountedIndexName), is(false)); - Request getSnaps = new Request("GET", "/_snapshot/" + snapshotRepo + "/_all"); - Map responseMap = responseAsMap(client().performRequest(getSnaps)); - assertThat(((List>) responseMap.get("snapshots")).size(), equalTo(1)); - }, 30, TimeUnit.SECONDS); + logger.info("--> waiting for [{}] to be deleted...", restoredPartiallyMountedIndexName); + awaitIndexDoesNotExist(restoredPartiallyMountedIndexName); + List> snapshots = getSnapshots(); + assertThat("expected to have only one snapshot, but got: " + snapshots, snapshots.size(), equalTo(1)); } public void testSecondSearchableSnapshotUsingDifferentRepoThrows() throws Exception { @@ -919,15 +807,9 @@ public void testSearchableSnapshotsInHotPhasePinnedToHotNodes() throws Exception indexDocument(client(), dataStream, true); final String restoredIndex = SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + firstGenIndex; - assertBusy(() -> { - logger.info("--> waiting for [{}] to exist...", restoredIndex); - assertTrue(indexExists(restoredIndex)); - }, 30, TimeUnit.SECONDS); - assertBusy( - () -> assertThat(getStepKeyForIndex(client(), restoredIndex), is(PhaseCompleteStep.finalStep("hot").getKey())), - 30, - TimeUnit.SECONDS - ); + logger.info("--> waiting for [{}] to exist...", restoredIndex); + awaitIndexExists(restoredIndex); + TimeSeriesRestDriver.awaitStepKey(client(), restoredIndex, "hot", PhaseCompleteStep.NAME, PhaseCompleteStep.NAME); Map hotIndexSettings = getIndexSettingsAsMap(restoredIndex); // searchable snapshots mounted in the hot phase should be pinned to hot nodes @@ -965,19 +847,11 @@ public void testSearchableSnapshotInvokesAsyncActionOnNewIndex() throws Exceptio assertThat(backingIndices.size(), equalTo(2)); String backingIndexName = backingIndices.getFirst(); String restoredIndexName = SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + backingIndexName; - assertTrue(waitUntil(() -> { - try { - return indexExists(restoredIndexName); - } catch (IOException e) { - return false; - } - }, 30, TimeUnit.SECONDS)); + awaitIndexExists(restoredIndexName); - assertBusy( - () -> { assertThat(explainIndex(client(), restoredIndexName).get("step"), is(PhaseCompleteStep.NAME)); }, - 30, - TimeUnit.SECONDS - ); + TimeSeriesRestDriver.awaitStepKey(client(), restoredIndexName, null, null, PhaseCompleteStep.NAME); + // Wait for the original index to be deleted, to ensure ILM has finished + awaitIndexDoesNotExist(backingIndexName); } public void testSearchableSnapshotTotalShardsPerNode() throws Exception { @@ -1013,15 +887,9 @@ public void testSearchableSnapshotTotalShardsPerNode() throws Exception { // wait for snapshot successfully mounted and ILM execution completed final String searchableSnapMountedIndexName = SearchableSnapshotAction.PARTIAL_RESTORED_INDEX_PREFIX + SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + index; - assertBusy(() -> { - logger.info("--> waiting for [{}] to exist...", searchableSnapMountedIndexName); - assertTrue(indexExists(searchableSnapMountedIndexName)); - }, 30, TimeUnit.SECONDS); - assertBusy(() -> { - Step.StepKey stepKeyForIndex = getStepKeyForIndex(client(), searchableSnapMountedIndexName); - assertThat(stepKeyForIndex.phase(), is("frozen")); - assertThat(stepKeyForIndex.name(), is(PhaseCompleteStep.NAME)); - }, 30, TimeUnit.SECONDS); + logger.info("--> waiting for [{}] to exist...", searchableSnapMountedIndexName); + awaitIndexExists(searchableSnapMountedIndexName); + TimeSeriesRestDriver.awaitStepKey(client(), searchableSnapMountedIndexName, "frozen", null, PhaseCompleteStep.NAME); // Wait for the original index to be deleted, to ensure ILM has finished awaitIndexDoesNotExist(index); @@ -1031,8 +899,8 @@ public void testSearchableSnapshotTotalShardsPerNode() throws Exception { Integer snapshotTotalShardsPerNode = Integer.valueOf((String) indexSettings.get(INDEX_TOTAL_SHARDS_PER_NODE_SETTING.getKey())); assertEquals( "expected total_shards_per_node to be " + totalShardsPerNode + ", but got: " + snapshotTotalShardsPerNode, - snapshotTotalShardsPerNode, - totalShardsPerNode + totalShardsPerNode, + snapshotTotalShardsPerNode ); } @@ -1073,13 +941,7 @@ public void testSearchableSnapshotReplicateFor() throws Exception { assertThat(backingIndices.size(), equalTo(2)); String backingIndexName = backingIndices.getFirst(); String restoredIndexName = SearchableSnapshotAction.FULL_RESTORED_INDEX_PREFIX + backingIndexName; - assertTrue(waitUntil(() -> { - try { - return indexExists(restoredIndexName); - } catch (IOException e) { - return false; - } - }, 30, TimeUnit.SECONDS)); + awaitIndexExists(restoredIndexName); // check that the index is in the expected step and has the expected step_info.message assertBusy(() -> { @@ -1121,11 +983,7 @@ public void testSearchableSnapshotReplicateFor() throws Exception { ); // check that the index has progressed because enough time has passed now that the policy is different - assertBusy(() -> { - Map explainResponse = explainIndex(client(), restoredIndexName); - assertThat(explainResponse.get("phase"), is("cold")); - assertThat(explainResponse.get("step"), is(PhaseCompleteStep.NAME)); - }, 30, TimeUnit.SECONDS); + TimeSeriesRestDriver.awaitStepKey(client(), restoredIndexName, "cold", null, PhaseCompleteStep.NAME); // check that it has the right number of replicas { @@ -1136,20 +994,6 @@ public void testSearchableSnapshotReplicateFor() throws Exception { } } - private Step.StepKey getKeyForIndex(Response response, String indexName) throws IOException { - Map responseMap; - try (InputStream is = response.getEntity().getContent()) { - responseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), is, true); - } - - @SuppressWarnings("unchecked") - Map indexResponse = ((Map>) responseMap.get("indices")).get(indexName); - String phase = (String) indexResponse.get("phase"); - String action = (String) indexResponse.get("action"); - String step = (String) indexResponse.get("step"); - return new Step.StepKey(phase, action, step); - } - /** * Prepares a data stream with the specified number of primary and replica shards, * creates a snapshot repository and ILM policy, applies a composable template, From 11211bad2170013b83c5c880954fa95c6cc5b39a Mon Sep 17 00:00:00 2001 From: Niels Bauman Date: Mon, 8 Sep 2025 12:46:32 -0300 Subject: [PATCH 2/2] Spotless --- .../xpack/ilm/actions/SearchableSnapshotActionIT.java | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/ilm/actions/SearchableSnapshotActionIT.java b/x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/ilm/actions/SearchableSnapshotActionIT.java index 478516030cca6..0f6c9b8689bc9 100644 --- a/x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/ilm/actions/SearchableSnapshotActionIT.java +++ b/x-pack/plugin/ilm/qa/multi-node/src/javaRestTest/java/org/elasticsearch/xpack/ilm/actions/SearchableSnapshotActionIT.java @@ -695,7 +695,6 @@ public void testResumingSearchableSnapshotFromPartialToFull() throws Exception { // Wait for the original index to be deleted, to ensure ILM has finished awaitIndexDoesNotExist(index); - // remove ILM from the partially mounted searchable snapshot { Request request = new Request("POST", "/" + partialMountedIndexName + "/_ilm/remove");