From e6f118a365837e87456ba4ce3fb2e64c0b00dd95 Mon Sep 17 00:00:00 2001 From: Keith Massey Date: Tue, 18 Feb 2025 17:13:13 -0600 Subject: [PATCH 1/8] Updating TransportRolloverAction.checkBlock so that non-write-index blocks do not prevent data stream rollover --- .../rollover/TransportRolloverAction.java | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java index 8a6e84645a92f..fb963e7c49b26 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java @@ -154,12 +154,28 @@ protected ClusterBlockException checkBlock(RolloverRequest request, ClusterState .build(), IndicesOptions.GatekeeperOptions.DEFAULT ); - - return state.blocks() - .indicesBlockedException( - ClusterBlockLevel.METADATA_WRITE, - indexNameExpressionResolver.concreteIndexNames(state, indicesOptions, request) - ); + ResolvedExpression resolvedRolloverTarget = SelectorResolver.parseExpression(request.getRolloverTarget(), request.indicesOptions()); + final IndexAbstraction indexAbstraction = state.metadata().getIndicesLookup().get(resolvedRolloverTarget.resource()); + if (indexAbstraction.getType().equals(IndexAbstraction.Type.DATA_STREAM)) { + DataStream dataStream = (DataStream) indexAbstraction; + boolean targetData = resolvedRolloverTarget.selector() != null && resolvedRolloverTarget.selector().shouldIncludeData(); + boolean targetFailureStore = resolvedRolloverTarget.selector() != null + && resolvedRolloverTarget.selector().shouldIncludeFailures(); + List indicesToCheck = new ArrayList<>(); + if (targetData) { + indicesToCheck.add(dataStream.getWriteIndex().getName()); + } + if (targetFailureStore) { + indicesToCheck.add(dataStream.getWriteFailureIndex().getName()); + } + return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_WRITE, indicesToCheck.toArray(new String[0])); + } else { + return state.blocks() + .indicesBlockedException( + ClusterBlockLevel.METADATA_WRITE, + indexNameExpressionResolver.concreteIndexNames(state, indicesOptions, request) + ); + } } @Override From d5cd8d5908013ee17c395e78416213e8caae8320 Mon Sep 17 00:00:00 2001 From: Keith Massey Date: Tue, 18 Feb 2025 17:15:37 -0600 Subject: [PATCH 2/8] Update docs/changelog/122905.yaml --- docs/changelog/122905.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 docs/changelog/122905.yaml diff --git a/docs/changelog/122905.yaml b/docs/changelog/122905.yaml new file mode 100644 index 0000000000000..eccd50a759734 --- /dev/null +++ b/docs/changelog/122905.yaml @@ -0,0 +1,6 @@ +pr: 122905 +summary: Updating `TransportRolloverAction.checkBlock` so that non-write-index blocks + do not prevent data stream rollover +area: Data streams +type: bug +issues: [] From fb78a5308b79a4f278701f92495bec06da03e930 Mon Sep 17 00:00:00 2001 From: Keith Massey Date: Tue, 18 Feb 2025 17:40:07 -0600 Subject: [PATCH 3/8] adding a check for nonexistent failure store --- .../action/admin/indices/rollover/TransportRolloverAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java index fb963e7c49b26..0496f5c71f67a 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java @@ -165,7 +165,7 @@ protected ClusterBlockException checkBlock(RolloverRequest request, ClusterState if (targetData) { indicesToCheck.add(dataStream.getWriteIndex().getName()); } - if (targetFailureStore) { + if (targetFailureStore && dataStream.getWriteFailureIndex() != null) { indicesToCheck.add(dataStream.getWriteFailureIndex().getName()); } return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_WRITE, indicesToCheck.toArray(new String[0])); From 64bc6407c8db4017dc00ead7c873c511abaf773a Mon Sep 17 00:00:00 2001 From: Keith Massey Date: Wed, 19 Feb 2025 10:53:45 -0600 Subject: [PATCH 4/8] fixing DataStreamLifecycleServiceIT --- .../lifecycle/DataStreamLifecycleServiceIT.java | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/modules/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/lifecycle/DataStreamLifecycleServiceIT.java b/modules/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/lifecycle/DataStreamLifecycleServiceIT.java index 1c00e3ad380dc..ddfc4561fe485 100644 --- a/modules/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/lifecycle/DataStreamLifecycleServiceIT.java +++ b/modules/data-streams/src/internalClusterTest/java/org/elasticsearch/datastreams/lifecycle/DataStreamLifecycleServiceIT.java @@ -104,6 +104,7 @@ import static org.elasticsearch.index.IndexSettings.LIFECYCLE_ORIGINATION_DATE; import static org.elasticsearch.indices.ShardLimitValidator.SETTING_CLUSTER_MAX_SHARDS_PER_NODE; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; +import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -785,14 +786,10 @@ public void testErrorRecordingOnRetention() throws Exception { ).get(); DataStreamLifecycleHealthInfo dslHealthInfoOnHealthNode = healthNodeResponse.getHealthInfo().dslHealthInfo(); assertThat(dslHealthInfoOnHealthNode, is(not(DataStreamLifecycleHealthInfo.NO_DSL_ERRORS))); - // perhaps surprisingly rollover and delete are error-ing due to the read_only block on the first generation - // index which prevents metadata updates so rolling over the data stream is also blocked (note that both indices error at - // the same time so they'll have an equal retry count - the order becomes of the results, usually ordered by retry count, - // becomes non deterministic, hence the dynamic matching of index name) - assertThat(dslHealthInfoOnHealthNode.dslErrorsInfo().size(), is(2)); + assertThat(dslHealthInfoOnHealthNode.dslErrorsInfo().size(), is(1)); DslErrorInfo errorInfo = dslHealthInfoOnHealthNode.dslErrorsInfo().get(0); assertThat(errorInfo.retryCount(), greaterThanOrEqualTo(3)); - assertThat(List.of(firstGenerationIndex, secondGenerationIndex).contains(errorInfo.indexName()), is(true)); + assertThat(errorInfo.indexName(), equalTo(firstGenerationIndex)); }); GetHealthAction.Response healthResponse = client().execute(GetHealthAction.INSTANCE, new GetHealthAction.Request(true, 1000)) @@ -808,15 +805,12 @@ public void testErrorRecordingOnRetention() throws Exception { assertThat(dslIndicator.impacts(), is(STAGNATING_INDEX_IMPACT)); assertThat( dslIndicator.symptom(), - is("2 backing indices have repeatedly encountered errors whilst trying to advance in its lifecycle") + is("A backing index has repeatedly encountered errors whilst trying to advance in its lifecycle") ); Diagnosis diagnosis = dslIndicator.diagnosisList().get(0); assertThat(diagnosis.definition(), is(STAGNATING_BACKING_INDICES_DIAGNOSIS_DEF)); - assertThat( - diagnosis.affectedResources().get(0).getValues(), - containsInAnyOrder(firstGenerationIndex, secondGenerationIndex) - ); + assertThat(diagnosis.affectedResources().get(0).getValues(), contains(firstGenerationIndex)); } // let's mark the index as writeable and make sure it's deleted and the error store is empty From 4375b13128ff168f306e991b6fd99681e85e2203 Mon Sep 17 00:00:00 2001 From: Keith Massey Date: Wed, 19 Feb 2025 11:30:30 -0600 Subject: [PATCH 5/8] adding unit tests --- .../TransportRolloverActionTests.java | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java index 657a03066ada9..d8ac453c58427 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java @@ -11,6 +11,7 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionRequest; +import org.elasticsearch.action.IndicesRequest; import org.elasticsearch.action.admin.indices.stats.CommonStats; import org.elasticsearch.action.admin.indices.stats.IndexStats; import org.elasticsearch.action.admin.indices.stats.IndicesStatsAction; @@ -24,6 +25,7 @@ import org.elasticsearch.client.internal.Client; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.block.ClusterBlocks; import org.elasticsearch.cluster.metadata.AliasMetadata; import org.elasticsearch.cluster.metadata.DataStream; import org.elasticsearch.cluster.metadata.IndexMetadata; @@ -43,6 +45,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.core.TimeValue; +import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexMode; import org.elasticsearch.index.IndexVersion; import org.elasticsearch.index.cache.query.QueryCacheStats; @@ -578,6 +581,110 @@ public void testRolloverAliasToDataStreamFails() throws Exception { assertThat(illegalStateException.getMessage(), containsString("Aliases to data streams cannot be rolled over.")); } + public void testCheckBlockForIndices() { + final TransportRolloverAction transportRolloverAction = new TransportRolloverAction( + mock(TransportService.class), + mockClusterService, + mockThreadPool, + mockActionFilters, + mockIndexNameExpressionResolver, + rolloverService, + mockClient, + mockAllocationService, + mockMetadataDataStreamService, + dataStreamAutoShardingService + ); + final IndexMetadata.Builder indexMetadata1 = IndexMetadata.builder("my-index-1") + .putAlias(AliasMetadata.builder("my-alias").writeIndex(true).build()) + .settings(settings(IndexVersion.current())) + .numberOfShards(1) + .numberOfReplicas(1); + final IndexMetadata indexMetadata2 = IndexMetadata.builder("my-index-2") + .settings(settings(IndexVersion.current()).put(IndexMetadata.INDEX_READ_ONLY_SETTING.getKey(), true)) + .numberOfShards(1) + .numberOfReplicas(1) + .build(); + final ClusterState stateBefore = ClusterState.builder(ClusterName.DEFAULT) + .metadata(Metadata.builder().put(indexMetadata1).put(indexMetadata2, false)) + .blocks(ClusterBlocks.builder().addBlocks(indexMetadata2)) + .build(); + { + RolloverRequest rolloverRequest = new RolloverRequest("my-alias", "my-new-index"); + when(mockIndexNameExpressionResolver.concreteIndexNames(any(), any(), (IndicesRequest) any())).thenReturn( + new String[] { "my-index-1" } + ); + assertNull(transportRolloverAction.checkBlock(rolloverRequest, stateBefore)); + } + { + RolloverRequest rolloverRequest = new RolloverRequest("my-index-2", "my-new-index"); + when(mockIndexNameExpressionResolver.concreteIndexNames(any(), any(), (IndicesRequest) any())).thenReturn( + new String[] { "my-index-2" } + ); + assertNotNull(transportRolloverAction.checkBlock(rolloverRequest, stateBefore)); + } + } + + public void testCheckBlockForDataStreams() { + final TransportRolloverAction transportRolloverAction = new TransportRolloverAction( + mock(TransportService.class), + mockClusterService, + mockThreadPool, + mockActionFilters, + mockIndexNameExpressionResolver, + rolloverService, + mockClient, + mockAllocationService, + mockMetadataDataStreamService, + dataStreamAutoShardingService + ); + { + // First, make sure checkBlock returns null when there are no blocks + final ClusterState clusterState = createDataStream(false, false); + RolloverRequest rolloverRequest = new RolloverRequest("my-data-stream", null); + assertNull(transportRolloverAction.checkBlock(rolloverRequest, clusterState)); + } + { + // Make sure checkBlock returns null when indices other than the write index have blocks + final ClusterState clusterState = createDataStream(false, true); + RolloverRequest rolloverRequest = new RolloverRequest("my-data-stream", null); + assertNull(transportRolloverAction.checkBlock(rolloverRequest, clusterState)); + } + { + // Make sure checkBlock returns an exception when the write index has a block + ClusterState clusterState = createDataStream(true, randomBoolean()); + RolloverRequest rolloverRequest = new RolloverRequest("my-data-stream", null); + assertNotNull(transportRolloverAction.checkBlock(rolloverRequest, clusterState)); + } + } + + private ClusterState createDataStream(boolean blockOnWriteIndex, boolean blocksOnNonWriteIndices) { + ClusterState.Builder clusterStateBuilder = ClusterState.builder(ClusterName.DEFAULT); + Metadata.Builder metadataBuilder = Metadata.builder(); + List indices = new ArrayList<>(); + int totalIndices = randomIntBetween(1, 20); + for (int i = 0; i < totalIndices; i++) { + Settings.Builder settingsBuilder = settings(IndexVersion.current()); + if ((blockOnWriteIndex && i == totalIndices - 1) || (blocksOnNonWriteIndices && i != totalIndices - 1)) { + settingsBuilder.put(IndexMetadata.INDEX_READ_ONLY_SETTING.getKey(), true); + } + final IndexMetadata backingIndexMetadata = IndexMetadata.builder(".ds-logs-ds-00000" + (i + 1)) + .settings(settingsBuilder) + .numberOfShards(1) + .numberOfReplicas(1) + .build(); + metadataBuilder.put(backingIndexMetadata, false); + indices.add(backingIndexMetadata.getIndex()); + clusterStateBuilder.blocks(ClusterBlocks.builder().addBlocks(backingIndexMetadata)); + } + + final DataStream dataStream = DataStream.builder("my-data-stream", indices) + .setMetadata(Map.of()) + .setIndexMode(IndexMode.STANDARD) + .build(); + metadataBuilder.put(dataStream); + return clusterStateBuilder.metadata(metadataBuilder).build(); + } + private IndicesStatsResponse createIndicesStatResponse(String indexName, long totalDocs, long primariesDocs) { final CommonStats primaryStats = mock(CommonStats.class); when(primaryStats.getDocs()).thenReturn(new DocsStats(primariesDocs, 0, between(1, 10000))); From 10bf632cc18222f964a2da46c95f92759966f84c Mon Sep 17 00:00:00 2001 From: Keith Massey Date: Wed, 19 Feb 2025 13:55:33 -0600 Subject: [PATCH 6/8] Fixing and test support for failure stores --- .../rollover/TransportRolloverAction.java | 18 ++- .../TransportRolloverActionTests.java | 137 ++++++++++++++++-- 2 files changed, 137 insertions(+), 18 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java index 0496f5c71f67a..c1aea0f0464eb 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java @@ -158,17 +158,21 @@ protected ClusterBlockException checkBlock(RolloverRequest request, ClusterState final IndexAbstraction indexAbstraction = state.metadata().getIndicesLookup().get(resolvedRolloverTarget.resource()); if (indexAbstraction.getType().equals(IndexAbstraction.Type.DATA_STREAM)) { DataStream dataStream = (DataStream) indexAbstraction; - boolean targetData = resolvedRolloverTarget.selector() != null && resolvedRolloverTarget.selector().shouldIncludeData(); boolean targetFailureStore = resolvedRolloverTarget.selector() != null && resolvedRolloverTarget.selector().shouldIncludeFailures(); - List indicesToCheck = new ArrayList<>(); - if (targetData) { - indicesToCheck.add(dataStream.getWriteIndex().getName()); + String indexToCheck; + if (targetFailureStore == false) { + indexToCheck = dataStream.getWriteIndex().getName(); + } else if (dataStream.getWriteFailureIndex() != null) { + indexToCheck = dataStream.getWriteFailureIndex().getName(); + } else { + indexToCheck = null; } - if (targetFailureStore && dataStream.getWriteFailureIndex() != null) { - indicesToCheck.add(dataStream.getWriteFailureIndex().getName()); + if (indexToCheck == null) { + return null; + } else { + return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_WRITE, new String[] { indexToCheck }); } - return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_WRITE, indicesToCheck.toArray(new String[0])); } else { return state.blocks() .indicesBlockedException( diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java index d8ac453c58427..6e39541491e96 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java @@ -20,11 +20,13 @@ import org.elasticsearch.action.admin.indices.stats.ShardStats; import org.elasticsearch.action.datastreams.autosharding.DataStreamAutoShardingService; import org.elasticsearch.action.support.ActionFilters; +import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.client.internal.Client; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlocks; import org.elasticsearch.cluster.metadata.AliasMetadata; import org.elasticsearch.cluster.metadata.DataStream; @@ -637,29 +639,124 @@ public void testCheckBlockForDataStreams() { mockMetadataDataStreamService, dataStreamAutoShardingService ); + String dataStreamName = randomAlphaOfLength(20); { // First, make sure checkBlock returns null when there are no blocks - final ClusterState clusterState = createDataStream(false, false); - RolloverRequest rolloverRequest = new RolloverRequest("my-data-stream", null); + final ClusterState clusterState = createDataStream( + dataStreamName, + false, + false, + randomBoolean(), + randomBoolean(), + randomBoolean() + ); + RolloverRequest rolloverRequest = new RolloverRequest(dataStreamName, null); assertNull(transportRolloverAction.checkBlock(rolloverRequest, clusterState)); } { // Make sure checkBlock returns null when indices other than the write index have blocks - final ClusterState clusterState = createDataStream(false, true); - RolloverRequest rolloverRequest = new RolloverRequest("my-data-stream", null); + final ClusterState clusterState = createDataStream( + dataStreamName, + false, + true, + randomBoolean(), + randomBoolean(), + randomBoolean() + ); + RolloverRequest rolloverRequest = new RolloverRequest(dataStreamName, null); + assertNull(transportRolloverAction.checkBlock(rolloverRequest, clusterState)); + } + { + // Make sure checkBlock returns null when indices other than the write index have blocks and we use "::data" + final ClusterState clusterState = createDataStream( + dataStreamName, + false, + true, + randomBoolean(), + randomBoolean(), + randomBoolean() + ); + RolloverRequest rolloverRequest = new RolloverRequest(dataStreamName + "::data", null); assertNull(transportRolloverAction.checkBlock(rolloverRequest, clusterState)); } { // Make sure checkBlock returns an exception when the write index has a block - ClusterState clusterState = createDataStream(true, randomBoolean()); - RolloverRequest rolloverRequest = new RolloverRequest("my-data-stream", null); + ClusterState clusterState = createDataStream( + dataStreamName, + true, + randomBoolean(), + randomBoolean(), + randomBoolean(), + randomBoolean() + ); + RolloverRequest rolloverRequest = new RolloverRequest(dataStreamName, null); + if (randomBoolean()) { + rolloverRequest.setIndicesOptions(IndicesOptions.lenientExpandOpenNoSelectors()); + } + ClusterBlockException e = transportRolloverAction.checkBlock(rolloverRequest, clusterState); + assertNotNull(e); + } + { + // Make sure checkBlock returns an exception when the write index has a block and we use "::data" + ClusterState clusterState = createDataStream( + dataStreamName, + true, + randomBoolean(), + randomBoolean(), + randomBoolean(), + randomBoolean() + ); + RolloverRequest rolloverRequest = new RolloverRequest(dataStreamName + "::data", null); + ClusterBlockException e = transportRolloverAction.checkBlock(rolloverRequest, clusterState); + assertNotNull(e); + } + } + + public void testCheckBlockForDataStreamFailureStores() { + final TransportRolloverAction transportRolloverAction = new TransportRolloverAction( + mock(TransportService.class), + mockClusterService, + mockThreadPool, + mockActionFilters, + mockIndexNameExpressionResolver, + rolloverService, + mockClient, + mockAllocationService, + mockMetadataDataStreamService, + dataStreamAutoShardingService + ); + String dataStreamName = randomAlphaOfLength(20); + { + // Make sure checkBlock returns no exception when there is no failure store block + ClusterState clusterState = createDataStream(dataStreamName, randomBoolean(), randomBoolean(), true, false, false); + RolloverRequest rolloverRequest = new RolloverRequest(dataStreamName + "::failures", null); + assertNull(transportRolloverAction.checkBlock(rolloverRequest, clusterState)); + } + { + // Make sure checkBlock returns an exception when the failure store write index has a block + ClusterState clusterState = createDataStream(dataStreamName, randomBoolean(), randomBoolean(), true, true, randomBoolean()); + RolloverRequest rolloverRequest = new RolloverRequest(dataStreamName + "::failures", null); assertNotNull(transportRolloverAction.checkBlock(rolloverRequest, clusterState)); } + { + // Make sure checkBlock returns an exception when failure store non-write indices has a block + ClusterState clusterState = createDataStream(dataStreamName, randomBoolean(), randomBoolean(), true, false, true); + RolloverRequest rolloverRequest = new RolloverRequest(dataStreamName + "::failures", null); + assertNull(transportRolloverAction.checkBlock(rolloverRequest, clusterState)); + } } - private ClusterState createDataStream(boolean blockOnWriteIndex, boolean blocksOnNonWriteIndices) { + private ClusterState createDataStream( + String dataStreamName, + boolean blockOnWriteIndex, + boolean blocksOnNonWriteIndices, + boolean includeFailureStore, + boolean blockOnFailureStoreWriteIndex, + boolean blockOnFailureStoreNonWriteIndices + ) { ClusterState.Builder clusterStateBuilder = ClusterState.builder(ClusterName.DEFAULT); Metadata.Builder metadataBuilder = Metadata.builder(); + ClusterBlocks.Builder clusterBlocksBuilder = ClusterBlocks.builder(); List indices = new ArrayList<>(); int totalIndices = randomIntBetween(1, 20); for (int i = 0; i < totalIndices; i++) { @@ -674,13 +771,31 @@ private ClusterState createDataStream(boolean blockOnWriteIndex, boolean blocksO .build(); metadataBuilder.put(backingIndexMetadata, false); indices.add(backingIndexMetadata.getIndex()); - clusterStateBuilder.blocks(ClusterBlocks.builder().addBlocks(backingIndexMetadata)); + clusterBlocksBuilder.addBlocks(backingIndexMetadata); } - final DataStream dataStream = DataStream.builder("my-data-stream", indices) + DataStream.Builder dataStreamBuilder = DataStream.builder(dataStreamName, indices) .setMetadata(Map.of()) - .setIndexMode(IndexMode.STANDARD) - .build(); + .setIndexMode(randomFrom(IndexMode.values())); + if (includeFailureStore) { + List failureStoreIndices = new ArrayList<>(); + int totalFailureStoreIndices = randomIntBetween(1, 20); + for (int i = 0; i < totalFailureStoreIndices; i++) { + Settings.Builder settingsBuilder = settings(IndexVersion.current()); + if ((blockOnFailureStoreWriteIndex && i == totalFailureStoreIndices - 1) + || (blockOnFailureStoreNonWriteIndices && i != totalFailureStoreIndices - 1)) { + settingsBuilder.put(IndexMetadata.INDEX_READ_ONLY_SETTING.getKey(), true); + } + final IndexMetadata failureStoreIndexMetadata = IndexMetadata.builder( + DataStream.getDefaultFailureStoreName(dataStreamName, i + 1, randomMillisUpToYear9999()) + ).settings(settingsBuilder).numberOfShards(1).numberOfReplicas(1).build(); + failureStoreIndices.add(failureStoreIndexMetadata.getIndex()); + clusterBlocksBuilder.addBlocks(failureStoreIndexMetadata); + } + dataStreamBuilder.setFailureIndices(DataStream.DataStreamIndices.failureIndicesBuilder(failureStoreIndices).build()); + } + clusterStateBuilder.blocks(clusterBlocksBuilder); + final DataStream dataStream = dataStreamBuilder.build(); metadataBuilder.put(dataStream); return clusterStateBuilder.metadata(metadataBuilder).build(); } From bba78bccc997e06ecfb23c40354560e0e3044d8a Mon Sep 17 00:00:00 2001 From: Keith Massey Date: Wed, 19 Feb 2025 14:21:11 -0600 Subject: [PATCH 7/8] reducing the number of return statements --- .../rollover/TransportRolloverAction.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java index c1aea0f0464eb..ccf3c1696851b 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java @@ -156,29 +156,30 @@ protected ClusterBlockException checkBlock(RolloverRequest request, ClusterState ); ResolvedExpression resolvedRolloverTarget = SelectorResolver.parseExpression(request.getRolloverTarget(), request.indicesOptions()); final IndexAbstraction indexAbstraction = state.metadata().getIndicesLookup().get(resolvedRolloverTarget.resource()); + final String[] indicesToCheck; if (indexAbstraction.getType().equals(IndexAbstraction.Type.DATA_STREAM)) { DataStream dataStream = (DataStream) indexAbstraction; boolean targetFailureStore = resolvedRolloverTarget.selector() != null && resolvedRolloverTarget.selector().shouldIncludeFailures(); - String indexToCheck; if (targetFailureStore == false) { - indexToCheck = dataStream.getWriteIndex().getName(); + assert dataStream.getWriteIndex() != null : dataStream.getName() + " is a data stream but has no write index"; + assert dataStream.getWriteIndex().getName() != null + : dataStream.getName() + " is a data stream but the write index is null"; + indicesToCheck = new String[] { dataStream.getWriteIndex().getName() }; } else if (dataStream.getWriteFailureIndex() != null) { - indexToCheck = dataStream.getWriteFailureIndex().getName(); + assert dataStream.getWriteFailureIndex().getName() != null + : "the write index for the data stream " + dataStream.getName() + " is null"; + indicesToCheck = new String[] { dataStream.getWriteFailureIndex().getName() }; } else { - indexToCheck = null; - } - if (indexToCheck == null) { - return null; - } else { - return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_WRITE, new String[] { indexToCheck }); + indicesToCheck = null; } } else { - return state.blocks() - .indicesBlockedException( - ClusterBlockLevel.METADATA_WRITE, - indexNameExpressionResolver.concreteIndexNames(state, indicesOptions, request) - ); + indicesToCheck = indexNameExpressionResolver.concreteIndexNames(state, indicesOptions, request); + } + if (indicesToCheck == null) { + return null; + } else { + return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA_WRITE, indicesToCheck); } } From 10a2023f3eece508a5ee2cea8456a480acb10acd Mon Sep 17 00:00:00 2001 From: Keith Massey Date: Thu, 20 Feb 2025 08:41:36 -0600 Subject: [PATCH 8/8] Fixing test comment --- .../admin/indices/rollover/TransportRolloverActionTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java index 6e39541491e96..5ea7968b0af6e 100644 --- a/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverActionTests.java @@ -739,7 +739,7 @@ public void testCheckBlockForDataStreamFailureStores() { assertNotNull(transportRolloverAction.checkBlock(rolloverRequest, clusterState)); } { - // Make sure checkBlock returns an exception when failure store non-write indices has a block + // Make sure checkBlock returns no exception when failure store non-write indices have a block ClusterState clusterState = createDataStream(dataStreamName, randomBoolean(), randomBoolean(), true, false, true); RolloverRequest rolloverRequest = new RolloverRequest(dataStreamName + "::failures", null); assertNull(transportRolloverAction.checkBlock(rolloverRequest, clusterState));