From fdc640f6e4fec14c6b8886715caae44f9251adeb Mon Sep 17 00:00:00 2001 From: Pete Gillin Date: Mon, 7 Apr 2025 16:16:35 +0100 Subject: [PATCH 1/2] Multi-project for `TransportExlainLifecycleAction` This converts this class to support multi-project. --- .../TransportExplainLifecycleAction.java | 34 +++++++++++-------- .../TransportExplainLifecycleActionTests.java | 24 ++++++------- .../build.gradle | 1 - 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportExplainLifecycleAction.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportExplainLifecycleAction.java index 0360a19b79193..01159fd01e459 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportExplainLifecycleAction.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/ilm/action/TransportExplainLifecycleAction.java @@ -11,14 +11,14 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.ChannelActionListener; -import org.elasticsearch.action.support.local.TransportLocalClusterStateAction; -import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.action.support.local.TransportLocalProjectMetadataAction; +import org.elasticsearch.cluster.ProjectState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.LifecycleExecutionState; -import org.elasticsearch.cluster.metadata.Metadata; +import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.cluster.project.ProjectResolver; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; @@ -52,7 +52,9 @@ import static org.elasticsearch.index.IndexSettings.LIFECYCLE_ORIGINATION_DATE; import static org.elasticsearch.xpack.core.ilm.WaitForRolloverReadyStep.applyDefaultConditions; -public class TransportExplainLifecycleAction extends TransportLocalClusterStateAction { +public class TransportExplainLifecycleAction extends TransportLocalProjectMetadataAction< + ExplainLifecycleRequest, + ExplainLifecycleResponse> { private final NamedXContentRegistry xContentRegistry; private final IndexNameExpressionResolver indexNameExpressionResolver; @@ -78,7 +80,8 @@ public TransportExplainLifecycleAction( actionFilters, transportService.getTaskManager(), clusterService, - threadPool.executor(ThreadPool.Names.MANAGEMENT) + threadPool.executor(ThreadPool.Names.MANAGEMENT), + projectResolver ); this.xContentRegistry = xContentRegistry; this.indexNameExpressionResolver = indexNameExpressionResolver; @@ -95,21 +98,25 @@ public TransportExplainLifecycleAction( } @Override - protected ClusterBlockException checkBlock(ExplainLifecycleRequest request, ClusterState state) { - return state.blocks() - .indicesBlockedException(ClusterBlockLevel.METADATA_READ, indexNameExpressionResolver.concreteIndexNames(state, request)); + protected ClusterBlockException checkBlock(ExplainLifecycleRequest request, ProjectState project) { + return project.blocks() + .indicesBlockedException( + project.projectId(), + ClusterBlockLevel.METADATA_READ, + indexNameExpressionResolver.concreteIndexNames(project.metadata(), request) + ); } @Override protected void localClusterStateOperation( Task task, ExplainLifecycleRequest request, - final ClusterState state, + ProjectState project, ActionListener listener ) { - String[] concreteIndices = indexNameExpressionResolver.concreteIndexNames(state, request); + String[] concreteIndices = indexNameExpressionResolver.concreteIndexNames(project.metadata(), request); boolean rolloverOnlyIfHasDocuments = LifecycleSettings.LIFECYCLE_ROLLOVER_ONLY_IF_HAS_DOCUMENTS_SETTING.get( - state.metadata().settings() + project.cluster().metadata().settings() ); Map indexResponses = new TreeMap<>(); for (String index : concreteIndices) { @@ -117,7 +124,7 @@ protected void localClusterStateOperation( try { indexResponse = getIndexLifecycleExplainResponse( index, - state.metadata(), + project.metadata(), request.onlyErrors(), request.onlyManaged(), xContentRegistry, @@ -140,13 +147,12 @@ protected void localClusterStateOperation( @Nullable static IndexLifecycleExplainResponse getIndexLifecycleExplainResponse( String indexName, - Metadata metadata, + ProjectMetadata project, boolean onlyErrors, boolean onlyManaged, NamedXContentRegistry xContentRegistry, boolean rolloverOnlyIfHasDocuments ) throws IOException { - final var project = metadata.getProject(); IndexMetadata indexMetadata = project.index(indexName); Settings idxSettings = indexMetadata.getSettings(); LifecycleExecutionState lifecycleState = indexMetadata.getLifecycleExecutionState(); diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/action/TransportExplainLifecycleActionTests.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/action/TransportExplainLifecycleActionTests.java index e89adafe91768..fe0c35aa360ce 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/action/TransportExplainLifecycleActionTests.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/action/TransportExplainLifecycleActionTests.java @@ -9,7 +9,7 @@ import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.metadata.LifecycleExecutionState; -import org.elasticsearch.cluster.metadata.Metadata; +import org.elasticsearch.cluster.metadata.ProjectMetadata; import org.elasticsearch.index.IndexVersion; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xcontent.NamedXContentRegistry; @@ -78,14 +78,14 @@ public void testGetIndexLifecycleExplainResponse() throws IOException { .numberOfReplicas(randomIntBetween(0, 5)) .putCustom(ILM_CUSTOM_METADATA_KEY, errorStepState.build().asMap()) .build(); - Metadata metadata = Metadata.builder() + ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) .put(indexMetadata, true) .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) .build(); IndexLifecycleExplainResponse onlyErrorsResponse = getIndexLifecycleExplainResponse( indexInErrorStep, - metadata, + project, true, true, REGISTRY, @@ -111,14 +111,14 @@ public void testGetIndexLifecycleExplainResponse() throws IOException { .numberOfReplicas(randomIntBetween(0, 5)) .putCustom(ILM_CUSTOM_METADATA_KEY, checkRolloverReadyStepState.build().asMap()) .build(); - Metadata metadata = Metadata.builder() + ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) .put(indexMetadata, true) .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) .build(); IndexLifecycleExplainResponse onlyErrorsResponse = getIndexLifecycleExplainResponse( indexInCheckRolloverStep, - metadata, + project, true, true, REGISTRY, @@ -128,7 +128,7 @@ public void testGetIndexLifecycleExplainResponse() throws IOException { IndexLifecycleExplainResponse allManagedResponse = getIndexLifecycleExplainResponse( indexInCheckRolloverStep, - metadata, + project, false, true, REGISTRY, @@ -150,14 +150,14 @@ public void testGetIndexLifecycleExplainResponse() throws IOException { .numberOfShards(randomIntBetween(1, 5)) .numberOfReplicas(randomIntBetween(0, 5)) .build(); - Metadata metadata = Metadata.builder() + ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) .put(indexMetadata, true) .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) .build(); IndexLifecycleExplainResponse onlyErrorsResponse = getIndexLifecycleExplainResponse( indexWithMissingPolicy, - metadata, + project, true, true, REGISTRY, @@ -175,14 +175,14 @@ public void testGetIndexLifecycleExplainResponse() throws IOException { .numberOfShards(randomIntBetween(1, 5)) .numberOfReplicas(randomIntBetween(0, 5)) .build(); - Metadata metadata = Metadata.builder() + ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) .put(indexMetadata, true) .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) .build(); IndexLifecycleExplainResponse onlyManaged = getIndexLifecycleExplainResponse( "index", - metadata, + project, false, true, REGISTRY, @@ -205,14 +205,14 @@ public void testGetIndexLifecycleExplainResponse() throws IOException { .numberOfReplicas(randomIntBetween(0, 5)) .putCustom(ILM_CUSTOM_METADATA_KEY, checkRolloverReadyStepState.build().asMap()) .build(); - Metadata metadata = Metadata.builder() + ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) .put(indexMetadata, true) .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) .build(); IndexLifecycleExplainResponse response = getIndexLifecycleExplainResponse( indexInCheckRolloverStep, - metadata, + project, false, true, REGISTRY, diff --git a/x-pack/qa/multi-project/xpack-rest-tests-with-multiple-projects/build.gradle b/x-pack/qa/multi-project/xpack-rest-tests-with-multiple-projects/build.gradle index b7c61ceef6dae..7ec46b7472820 100644 --- a/x-pack/qa/multi-project/xpack-rest-tests-with-multiple-projects/build.gradle +++ b/x-pack/qa/multi-project/xpack-rest-tests-with-multiple-projects/build.gradle @@ -49,7 +49,6 @@ tasks.named("yamlRestTest").configure { '^ilm/10_basic/Test Undeletable Policy In Use', '^ilm/20_move_to_step/*', '^ilm/30_retry/*', - '^ilm/40_explain_lifecycle/*', '^ilm/60_operation_mode/*', '^ilm/60_remove_policy_for_index/*', '^ilm/70_downsampling/*', From 4fcd00c3918193fbe61d7cea7d89377d972969a2 Mon Sep 17 00:00:00 2001 From: Pete Gillin Date: Mon, 7 Apr 2025 16:40:03 +0100 Subject: [PATCH 2/2] Drive-by refactoring to split multiple independent tests in one method into separate methods --- .../TransportExplainLifecycleActionTests.java | 303 +++++++++--------- 1 file changed, 148 insertions(+), 155 deletions(-) diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/action/TransportExplainLifecycleActionTests.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/action/TransportExplainLifecycleActionTests.java index fe0c35aa360ce..ac9db78d2a3b2 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/action/TransportExplainLifecycleActionTests.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/ilm/action/TransportExplainLifecycleActionTests.java @@ -63,165 +63,158 @@ public class TransportExplainLifecycleActionTests extends ESTestCase { ); } - public void testGetIndexLifecycleExplainResponse() throws IOException { - { - // only errors index - LifecycleExecutionState.Builder errorStepState = LifecycleExecutionState.builder() - .setPhase("hot") - .setAction("rollover") - .setStep(ErrorStep.NAME) - .setPhaseDefinition(PHASE_DEFINITION); - String indexInErrorStep = "index_in_error"; - IndexMetadata indexMetadata = IndexMetadata.builder(indexInErrorStep) - .settings(settings(IndexVersion.current()).put(LifecycleSettings.LIFECYCLE_NAME, POLICY_NAME)) - .numberOfShards(randomIntBetween(1, 5)) - .numberOfReplicas(randomIntBetween(0, 5)) - .putCustom(ILM_CUSTOM_METADATA_KEY, errorStepState.build().asMap()) - .build(); - ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) - .put(indexMetadata, true) - .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) - .build(); - - IndexLifecycleExplainResponse onlyErrorsResponse = getIndexLifecycleExplainResponse( - indexInErrorStep, - project, - true, - true, - REGISTRY, - randomBoolean() - ); - assertThat(onlyErrorsResponse, notNullValue()); - assertThat(onlyErrorsResponse.getIndex(), is(indexInErrorStep)); - assertThat(onlyErrorsResponse.getStep(), is(ErrorStep.NAME)); - } + public void testGetIndexLifecycleExplainResponse_onlyErrors() throws IOException { + LifecycleExecutionState.Builder errorStepState = LifecycleExecutionState.builder() + .setPhase("hot") + .setAction("rollover") + .setStep(ErrorStep.NAME) + .setPhaseDefinition(PHASE_DEFINITION); + String indexInErrorStep = "index_in_error"; + IndexMetadata indexMetadata = IndexMetadata.builder(indexInErrorStep) + .settings(settings(IndexVersion.current()).put(LifecycleSettings.LIFECYCLE_NAME, POLICY_NAME)) + .numberOfShards(randomIntBetween(1, 5)) + .numberOfReplicas(randomIntBetween(0, 5)) + .putCustom(ILM_CUSTOM_METADATA_KEY, errorStepState.build().asMap()) + .build(); + ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) + .put(indexMetadata, true) + .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) + .build(); + + IndexLifecycleExplainResponse onlyErrorsResponse = getIndexLifecycleExplainResponse( + indexInErrorStep, + project, + true, + true, + REGISTRY, + randomBoolean() + ); + assertThat(onlyErrorsResponse, notNullValue()); + assertThat(onlyErrorsResponse.getIndex(), is(indexInErrorStep)); + assertThat(onlyErrorsResponse.getStep(), is(ErrorStep.NAME)); + } - { - // only managed index - LifecycleExecutionState.Builder checkRolloverReadyStepState = LifecycleExecutionState.builder() - .setPhase("hot") - .setAction("rollover") - .setStep(WaitForRolloverReadyStep.NAME) - .setPhaseDefinition(PHASE_DEFINITION); - - String indexInCheckRolloverStep = "index_in_check_rollover"; - IndexMetadata indexMetadata = IndexMetadata.builder(indexInCheckRolloverStep) - .settings(settings(IndexVersion.current()).put(LifecycleSettings.LIFECYCLE_NAME, POLICY_NAME)) - .numberOfShards(randomIntBetween(1, 5)) - .numberOfReplicas(randomIntBetween(0, 5)) - .putCustom(ILM_CUSTOM_METADATA_KEY, checkRolloverReadyStepState.build().asMap()) - .build(); - ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) - .put(indexMetadata, true) - .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) - .build(); - - IndexLifecycleExplainResponse onlyErrorsResponse = getIndexLifecycleExplainResponse( - indexInCheckRolloverStep, - project, - true, - true, - REGISTRY, - randomBoolean() - ); - assertThat(onlyErrorsResponse, nullValue()); - - IndexLifecycleExplainResponse allManagedResponse = getIndexLifecycleExplainResponse( - indexInCheckRolloverStep, - project, - false, - true, - REGISTRY, - randomBoolean() - ); - assertThat(allManagedResponse, notNullValue()); - assertThat(allManagedResponse.getIndex(), is(indexInCheckRolloverStep)); - assertThat(allManagedResponse.getStep(), is(WaitForRolloverReadyStep.NAME)); - } + public void testGetIndexLifecycleExplainResponse_onlyManagedIndex() throws IOException { + LifecycleExecutionState.Builder checkRolloverReadyStepState = LifecycleExecutionState.builder() + .setPhase("hot") + .setAction("rollover") + .setStep(WaitForRolloverReadyStep.NAME) + .setPhaseDefinition(PHASE_DEFINITION); + + String indexInCheckRolloverStep = "index_in_check_rollover"; + IndexMetadata indexMetadata = IndexMetadata.builder(indexInCheckRolloverStep) + .settings(settings(IndexVersion.current()).put(LifecycleSettings.LIFECYCLE_NAME, POLICY_NAME)) + .numberOfShards(randomIntBetween(1, 5)) + .numberOfReplicas(randomIntBetween(0, 5)) + .putCustom(ILM_CUSTOM_METADATA_KEY, checkRolloverReadyStepState.build().asMap()) + .build(); + ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) + .put(indexMetadata, true) + .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) + .build(); + + IndexLifecycleExplainResponse onlyErrorsResponse = getIndexLifecycleExplainResponse( + indexInCheckRolloverStep, + project, + true, + true, + REGISTRY, + randomBoolean() + ); + assertThat(onlyErrorsResponse, nullValue()); + + IndexLifecycleExplainResponse allManagedResponse = getIndexLifecycleExplainResponse( + indexInCheckRolloverStep, + project, + false, + true, + REGISTRY, + randomBoolean() + ); + assertThat(allManagedResponse, notNullValue()); + assertThat(allManagedResponse.getIndex(), is(indexInCheckRolloverStep)); + assertThat(allManagedResponse.getStep(), is(WaitForRolloverReadyStep.NAME)); + } - { - // index with missing policy - IndexLifecycleService indexLifecycleService = mock(IndexLifecycleService.class); - when(indexLifecycleService.policyExists("random-policy")).thenReturn(false); - - String indexWithMissingPolicy = "index_with_missing_policy"; - IndexMetadata indexMetadata = IndexMetadata.builder(indexWithMissingPolicy) - .settings(settings(IndexVersion.current()).put(LifecycleSettings.LIFECYCLE_NAME, "random-policy")) - .numberOfShards(randomIntBetween(1, 5)) - .numberOfReplicas(randomIntBetween(0, 5)) - .build(); - ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) - .put(indexMetadata, true) - .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) - .build(); - - IndexLifecycleExplainResponse onlyErrorsResponse = getIndexLifecycleExplainResponse( - indexWithMissingPolicy, - project, - true, - true, - REGISTRY, - randomBoolean() - ); - assertThat(onlyErrorsResponse, notNullValue()); - assertThat(onlyErrorsResponse.getPolicyName(), is("random-policy")); - assertThat(onlyErrorsResponse.getStep(), is(ErrorStep.NAME)); - } + public void testGetIndexLifecycleExplainResponse_indexWithMissingPolicy() throws IOException { + IndexLifecycleService indexLifecycleService = mock(IndexLifecycleService.class); + when(indexLifecycleService.policyExists("random-policy")).thenReturn(false); + + String indexWithMissingPolicy = "index_with_missing_policy"; + IndexMetadata indexMetadata = IndexMetadata.builder(indexWithMissingPolicy) + .settings(settings(IndexVersion.current()).put(LifecycleSettings.LIFECYCLE_NAME, "random-policy")) + .numberOfShards(randomIntBetween(1, 5)) + .numberOfReplicas(randomIntBetween(0, 5)) + .build(); + ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) + .put(indexMetadata, true) + .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) + .build(); + + IndexLifecycleExplainResponse onlyErrorsResponse = getIndexLifecycleExplainResponse( + indexWithMissingPolicy, + project, + true, + true, + REGISTRY, + randomBoolean() + ); + assertThat(onlyErrorsResponse, notNullValue()); + assertThat(onlyErrorsResponse.getPolicyName(), is("random-policy")); + assertThat(onlyErrorsResponse.getStep(), is(ErrorStep.NAME)); + } - { - // not managed index - IndexMetadata indexMetadata = IndexMetadata.builder("index") - .settings(settings(IndexVersion.current())) - .numberOfShards(randomIntBetween(1, 5)) - .numberOfReplicas(randomIntBetween(0, 5)) - .build(); - ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) - .put(indexMetadata, true) - .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) - .build(); - - IndexLifecycleExplainResponse onlyManaged = getIndexLifecycleExplainResponse( - "index", - project, - false, - true, - REGISTRY, - randomBoolean() - ); - assertThat(onlyManaged, nullValue()); - } + public void testGetIndexLifecycleExplainResponse_notManagedIndex() throws IOException { + IndexMetadata indexMetadata = IndexMetadata.builder("index") + .settings(settings(IndexVersion.current())) + .numberOfShards(randomIntBetween(1, 5)) + .numberOfReplicas(randomIntBetween(0, 5)) + .build(); + ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) + .put(indexMetadata, true) + .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) + .build(); + + IndexLifecycleExplainResponse onlyManaged = getIndexLifecycleExplainResponse( + "index", + project, + false, + true, + REGISTRY, + randomBoolean() + ); + assertThat(onlyManaged, nullValue()); + } - { - // validate addition of default condition with `rolloverOnlyIfHasDocuments` true - LifecycleExecutionState.Builder checkRolloverReadyStepState = LifecycleExecutionState.builder() - .setPhase("hot") - .setAction("rollover") - .setStep(WaitForRolloverReadyStep.NAME) - .setPhaseDefinition(PHASE_DEFINITION); - String indexInCheckRolloverStep = "index_in_check_rollover"; - IndexMetadata indexMetadata = IndexMetadata.builder(indexInCheckRolloverStep) - .settings(settings(IndexVersion.current()).put(LifecycleSettings.LIFECYCLE_NAME, POLICY_NAME)) - .numberOfShards(randomIntBetween(1, 5)) - .numberOfReplicas(randomIntBetween(0, 5)) - .putCustom(ILM_CUSTOM_METADATA_KEY, checkRolloverReadyStepState.build().asMap()) - .build(); - ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) - .put(indexMetadata, true) - .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) - .build(); - - IndexLifecycleExplainResponse response = getIndexLifecycleExplainResponse( - indexInCheckRolloverStep, - project, - false, - true, - REGISTRY, - true - ); - var rolloverAction = ((RolloverAction) response.getPhaseExecutionInfo().getPhase().getActions().get(RolloverAction.NAME)); - assertThat(rolloverAction, notNullValue()); - assertThat(rolloverAction.getConditions().getMinDocs(), is(1L)); - } + public void testGetIndexLifecycleExplainResponse_rolloverOnlyIfHasDocuments_addsCondition() throws IOException { + LifecycleExecutionState.Builder checkRolloverReadyStepState = LifecycleExecutionState.builder() + .setPhase("hot") + .setAction("rollover") + .setStep(WaitForRolloverReadyStep.NAME) + .setPhaseDefinition(PHASE_DEFINITION); + String indexInCheckRolloverStep = "index_in_check_rollover"; + IndexMetadata indexMetadata = IndexMetadata.builder(indexInCheckRolloverStep) + .settings(settings(IndexVersion.current()).put(LifecycleSettings.LIFECYCLE_NAME, POLICY_NAME)) + .numberOfShards(randomIntBetween(1, 5)) + .numberOfReplicas(randomIntBetween(0, 5)) + .putCustom(ILM_CUSTOM_METADATA_KEY, checkRolloverReadyStepState.build().asMap()) + .build(); + ProjectMetadata project = ProjectMetadata.builder(randomProjectIdOrDefault()) + .put(indexMetadata, true) + .putCustom(IndexLifecycleMetadata.TYPE, createIndexLifecycleMetadata()) + .build(); + + IndexLifecycleExplainResponse response = getIndexLifecycleExplainResponse( + indexInCheckRolloverStep, + project, + false, + true, + REGISTRY, + true + ); + var rolloverAction = ((RolloverAction) response.getPhaseExecutionInfo().getPhase().getActions().get(RolloverAction.NAME)); + assertThat(rolloverAction, notNullValue()); + assertThat(rolloverAction.getConditions().getMinDocs(), is(1L)); } private static IndexLifecycleMetadata createIndexLifecycleMetadata() {