diff --git a/CHANGELOG.md b/CHANGELOG.md index 798be4678e550..5b6b0343e397c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -126,6 +126,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Removed ### Fixed +- Add more index blocks check for resize APIs ([#6774](https://github.com/opensearch-project/OpenSearch/pull/6774)) - Replaces ZipInputStream with ZipFile to fix Zip Slip vulnerability ([#7230](https://github.com/opensearch-project/OpenSearch/pull/7230)) - Add missing validation/parsing of SearchBackpressureMode of SearchBackpressureSettings ([#7541](https://github.com/opensearch-project/OpenSearch/pull/7541)) diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.clone/10_basic.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.clone/10_basic.yml index ca8342b2e91c2..d92fb434ba718 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.clone/10_basic.yml +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.clone/10_basic.yml @@ -112,3 +112,99 @@ setup: settings: index.number_of_replicas: 0 index.number_of_shards: 6 + +--- +"Returns error if target index's metadata write is blocked": + + - skip: + version: " - 2.9.99" + reason: "only available in 3.0+" + + # block source index's write operations + - do: + indices.put_settings: + index: source + body: + index.blocks.write: true + index.number_of_replicas: 0 + + - do: + cluster.health: + wait_for_status: green + index: source + + # set `index.blocks.read_only` to `true` for target index + - do: + catch: /action_request_validation_exception/ + indices.clone: + index: "source" + target: "new_cloned_index" + wait_for_active_shards: 1 + cluster_manager_timeout: 10s + body: + settings: + index.number_of_replicas: 0 + index.blocks.read_only: true + + # set `index.blocks.metadata` to `true` for target index + - do: + catch: /action_request_validation_exception/ + indices.clone: + index: "source" + target: "new_cloned_index" + wait_for_active_shards: 1 + cluster_manager_timeout: 10s + body: + settings: + index.number_of_replicas: 0 + index.blocks.metadata: true + + # set source index's setting `index.blocks.read_only` to `true` + - do: + indices.put_settings: + index: source + body: + index.blocks.read_only: true + + - do: + catch: /illegal_argument_exception/ + indices.clone: + index: "source" + target: "new_cloned_index" + wait_for_active_shards: 1 + cluster_manager_timeout: 10s + body: + settings: + index.number_of_replicas: 0 + + # overwrite the source index's setting, everything is fine + - do: + indices.clone: + index: "source" + target: "new_cloned_index" + wait_for_active_shards: 1 + cluster_manager_timeout: 10s + body: + settings: + index.number_of_replicas: 0 + index.blocks.read_only: null + + - do: + cluster.health: + wait_for_status: green + + - do: + get: + index: new_cloned_index + id: "1" + + - match: { _index: new_cloned_index } + - match: { _id: "1" } + - match: { _source: { foo: "hello world" } } + + # clear the source index's read_only blocks because it will block deleting index + - do: + indices.put_settings: + index: source + body: + index.blocks.read_only: null diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.shrink/10_basic.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.shrink/10_basic.yml index 032f061d8a160..3b89d5c93acd8 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.shrink/10_basic.yml +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.shrink/10_basic.yml @@ -1,15 +1,11 @@ --- -"Shrink index via API": +setup: # creates an index with one document solely allocated on a particular data node # and shrinks it into a new index with a single shard # we don't do the relocation to a single node after the index is created # here since in a mixed version cluster we can't identify # which node is the one with the highest version and that is the only one that can safely # be used to shrink the index. - - - skip: - features: allowed_warnings - - do: nodes.info: node_id: data:true @@ -32,14 +28,10 @@ id: "1" body: { "foo": "hello world" } - - do: - get: - index: source - id: "1" - - - match: { _index: source } - - match: { _id: "1" } - - match: { _source: { foo: "hello world" } } +--- +"Shrink index via API": + - skip: + features: allowed_warnings # make it read-only - do: @@ -79,3 +71,103 @@ - match: { _index: target } - match: { _id: "1" } - match: { _source: { foo: "hello world" } } + +--- +"Returns error if target index's metadata write is blocked": + + - skip: + version: " - 2.9.99" + reason: "only available in 3.0+" + + # block source index's write operations + - do: + indices.put_settings: + index: source + body: + index.blocks.write: true + index.number_of_replicas: 0 + + - do: + cluster.health: + wait_for_status: green + index: source + + # set `index.blocks.read_only` to `true` for target index + - do: + catch: /action_request_validation_exception/ + indices.shrink: + index: "source" + target: "new_shrunken_index" + wait_for_active_shards: 1 + cluster_manager_timeout: 10s + body: + settings: + index.number_of_replicas: 0 + index.number_of_shards: 1 + index.blocks.read_only: true + + # set `index.blocks.metadata` to `true` for target index + - do: + catch: /action_request_validation_exception/ + indices.shrink: + index: "source" + target: "new_shrunken_index" + wait_for_active_shards: 1 + cluster_manager_timeout: 10s + body: + settings: + index.number_of_replicas: 0 + index.number_of_shards: 1 + index.blocks.metadata: true + + # set source index's setting `index.blocks.read_only` to `true` + - do: + indices.put_settings: + index: source + body: + index.blocks.read_only: true + + - do: + catch: /illegal_argument_exception/ + indices.shrink: + index: "source" + target: "new_shrunken_index" + wait_for_active_shards: 1 + cluster_manager_timeout: 10s + body: + settings: + index.number_of_replicas: 0 + index.number_of_shards: 1 + + # overwrite the source index's setting, everything is fine + - do: + indices.shrink: + index: "source" + target: "new_shrunken_index" + wait_for_active_shards: 1 + cluster_manager_timeout: 10s + body: + settings: + index.number_of_replicas: 0 + index.number_of_shards: 1 + index.blocks.read_only: null + + - do: + cluster.health: + wait_for_status: green + + - do: + get: + index: new_shrunken_index + id: "1" + + - match: { _index: new_shrunken_index } + - match: { _id: "1" } + - match: { _source: { foo: "hello world" } } + + # clear the source index's read_only blocks because it will block deleting index + - do: + indices.put_settings: + index: source + body: + index.blocks.read_only: null diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.split/10_basic.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.split/10_basic.yml index 2432f47d4dca7..5e1cae0d8efc5 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.split/10_basic.yml +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.split/10_basic.yml @@ -218,3 +218,103 @@ setup: settings: index.number_of_replicas: 0 index.number_of_shards: 6 + +--- +"Returns error if target index's metadata write is blocked": + + - skip: + version: " - 2.9.99" + reason: "only available in 3.0+" + + # block source index's write operations + - do: + indices.put_settings: + index: source + body: + index.blocks.write: true + index.number_of_replicas: 0 + + - do: + cluster.health: + wait_for_status: green + index: source + + # set `index.blocks.read_only` to `true` for target index + - do: + catch: /action_request_validation_exception/ + indices.split: + index: "source" + target: "new_split_index" + wait_for_active_shards: 1 + cluster_manager_timeout: 10s + body: + settings: + index.number_of_replicas: 0 + index.number_of_shards: 4 + index.blocks.read_only: true + + # set `index.blocks.metadata` to `true` for target index + - do: + catch: /action_request_validation_exception/ + indices.split: + index: "source" + target: "new_split_index" + wait_for_active_shards: 1 + cluster_manager_timeout: 10s + body: + settings: + index.number_of_replicas: 0 + index.number_of_shards: 4 + index.blocks.metadata: true + + # set source index's setting `index.blocks.read_only` to `true` + - do: + indices.put_settings: + index: source + body: + index.blocks.read_only: true + + - do: + catch: /illegal_argument_exception/ + indices.split: + index: "source" + target: "new_split_index" + wait_for_active_shards: 1 + cluster_manager_timeout: 10s + body: + settings: + index.number_of_replicas: 0 + index.number_of_shards: 4 + + # overwrite the source index's setting, everything is fine + - do: + indices.split: + index: "source" + target: "new_split_index" + wait_for_active_shards: 1 + cluster_manager_timeout: 10s + body: + settings: + index.number_of_replicas: 0 + index.number_of_shards: 4 + index.blocks.read_only: null + + - do: + cluster.health: + wait_for_status: green + + - do: + get: + index: new_split_index + id: "1" + + - match: { _index: new_split_index } + - match: { _id: "1" } + - match: { _source: { foo: "hello world" } } + + # clear the source index's read_only blocks because it will block deleting index + - do: + indices.put_settings: + index: source + body: + index.blocks.read_only: null diff --git a/server/src/main/java/org/opensearch/action/admin/indices/shrink/ResizeRequest.java b/server/src/main/java/org/opensearch/action/admin/indices/shrink/ResizeRequest.java index 1e524e720da9b..78636fd04984b 100644 --- a/server/src/main/java/org/opensearch/action/admin/indices/shrink/ResizeRequest.java +++ b/server/src/main/java/org/opensearch/action/admin/indices/shrink/ResizeRequest.java @@ -146,6 +146,27 @@ public ActionRequestValidationException validate() { if (maxShardSize != null && maxShardSize.getBytes() <= 0) { validationException = addValidationError("max_shard_size must be greater than 0", validationException); } + // Check target index's settings, if `index.blocks.read_only` is `true`, the target index's metadata writes will be disabled + // and then cause the new shards to be unassigned. + if (IndexMetadata.INDEX_READ_ONLY_SETTING.get(targetIndexRequest.settings()) == true) { + validationException = addValidationError( + "target index [" + + targetIndexRequest.index() + + "] will be blocked by [index.blocks.read_only=true], this will disable metadata writes and cause the shards to be unassigned", + validationException + ); + } + + // Check target index's settings, if `index.blocks.metadata` is `true`, the target index's metadata writes will be disabled + // and then cause the new shards to be unassigned. + if (IndexMetadata.INDEX_BLOCKS_METADATA_SETTING.get(targetIndexRequest.settings()) == true) { + validationException = addValidationError( + "target index [" + + targetIndexRequest.index() + + "] will be blocked by [index.blocks.metadata=true], this will disable metadata writes and cause the shards to be unassigned", + validationException + ); + } assert copySettings == null || copySettings; return validationException; } diff --git a/server/src/main/java/org/opensearch/action/admin/indices/shrink/TransportResizeAction.java b/server/src/main/java/org/opensearch/action/admin/indices/shrink/TransportResizeAction.java index 5bcf3631bf398..fe60a82d0e76f 100644 --- a/server/src/main/java/org/opensearch/action/admin/indices/shrink/TransportResizeAction.java +++ b/server/src/main/java/org/opensearch/action/admin/indices/shrink/TransportResizeAction.java @@ -181,6 +181,21 @@ static CreateIndexClusterStateUpdateRequest prepareCreateIndexRequest( final Settings targetIndexSettings = targetIndexSettingsBuilder.build(); final int numShards; + // We should check the source index's setting `index.blocks.read_only`, because the setting will be copied to target index, + // it will block target index's metadata writes and then cause the new shards to be unassigned, + // but if user overwrites the setting to `false` or `null`, everything is fine. + // We don't need to check the setting `index.blocks.metadata`, because it was checked when fetching index stats + if (IndexMetadata.INDEX_READ_ONLY_SETTING.get(metadata.getSettings()) == true + && IndexMetadata.INDEX_READ_ONLY_SETTING.exists(targetIndexSettings) == false) { + throw new IllegalArgumentException( + "target index [" + + targetIndexName + + "] will be blocked by [index.blocks.read_only=true] which is copied from the source index [" + + sourceIndexName + + "], this will disable metadata writes and cause the shards to be unassigned" + ); + } + if (IndexMetadata.INDEX_NUMBER_OF_SHARDS_SETTING.exists(targetIndexSettings)) { numShards = IndexMetadata.INDEX_NUMBER_OF_SHARDS_SETTING.get(targetIndexSettings); } else { diff --git a/server/src/main/java/org/opensearch/cluster/metadata/IndexMetadata.java b/server/src/main/java/org/opensearch/cluster/metadata/IndexMetadata.java index 4ca79541637b1..e7fee330f5b00 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/IndexMetadata.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/IndexMetadata.java @@ -2011,8 +2011,8 @@ public static ShardId selectCloneShard(int shardId, IndexMetadata sourceIndexMet throw new IllegalArgumentException( "the number of target shards (" + numTargetShards - + ") must be the same as the number of " - + " source shards ( " + + ") must be the same as the number of" + + " source shards (" + numSourceShards + ")" ); diff --git a/server/src/main/java/org/opensearch/cluster/metadata/MetadataCreateIndexService.java b/server/src/main/java/org/opensearch/cluster/metadata/MetadataCreateIndexService.java index bc57b2ff56da3..d3cb68d65affe 100644 --- a/server/src/main/java/org/opensearch/cluster/metadata/MetadataCreateIndexService.java +++ b/server/src/main/java/org/opensearch/cluster/metadata/MetadataCreateIndexService.java @@ -1389,9 +1389,11 @@ static IndexMetadata validateResize(ClusterState state, String sourceIndex, Stri ); } - // ensure index is read-only + // ensure write operations on the source index is blocked if (state.blocks().indexBlocked(ClusterBlockLevel.WRITE, sourceIndex) == false) { - throw new IllegalStateException("index " + sourceIndex + " must be read-only to resize index. use \"index.blocks.write=true\""); + throw new IllegalStateException( + "index " + sourceIndex + " must block write operations to resize index. use \"index.blocks.write=true\"" + ); } if (IndexMetadata.INDEX_NUMBER_OF_SHARDS_SETTING.exists(targetIndexSettings)) { diff --git a/server/src/test/java/org/opensearch/action/admin/indices/shrink/ResizeRequestTests.java b/server/src/test/java/org/opensearch/action/admin/indices/shrink/ResizeRequestTests.java index d591c395d5402..4742157b3209b 100644 --- a/server/src/test/java/org/opensearch/action/admin/indices/shrink/ResizeRequestTests.java +++ b/server/src/test/java/org/opensearch/action/admin/indices/shrink/ResizeRequestTests.java @@ -130,13 +130,36 @@ public void testToAndFromXContent() throws IOException { public void testTargetIndexSettingsValidation() { ResizeRequest resizeRequest = new ResizeRequest(randomAlphaOfLengthBetween(3, 10), randomAlphaOfLengthBetween(3, 10)); CreateIndexRequest createIndexRequest = new CreateIndexRequest(randomAlphaOfLengthBetween(3, 10)); + createIndexRequest.settings(Settings.builder().put("index.blocks.read_only", true)); + resizeRequest.setTargetIndex(createIndexRequest); + ActionRequestValidationException e = resizeRequest.validate(); + assertEquals( + "Validation Failed: 1: target index [" + + createIndexRequest.index() + + "] will be blocked by [index.blocks.read_only=true]," + + " this will disable metadata writes and cause the shards to be unassigned;", + e.getMessage() + ); + + createIndexRequest.settings(Settings.builder().put("index.blocks.metadata", true)); + resizeRequest.setMaxShardSize(new ByteSizeValue(randomIntBetween(1, 100))); + resizeRequest.setTargetIndex(createIndexRequest); + e = resizeRequest.validate(); + assertEquals( + "Validation Failed: 1: target index [" + + createIndexRequest.index() + + "] will be blocked by [index.blocks.metadata=true]," + + " this will disable metadata writes and cause the shards to be unassigned;", + e.getMessage() + ); + createIndexRequest.settings( Settings.builder() .put("index.sort.field", randomAlphaOfLengthBetween(3, 10)) .put("index.routing_partition_size", randomIntBetween(1, 10)) ); resizeRequest.setTargetIndex(createIndexRequest); - ActionRequestValidationException e = resizeRequest.validate(); + e = resizeRequest.validate(); assertEquals( "Validation Failed: 1: can't override index sort when resizing an index;" + "2: cannot provide a routing partition size value when resizing an index;", diff --git a/server/src/test/java/org/opensearch/action/admin/indices/shrink/TransportResizeActionTests.java b/server/src/test/java/org/opensearch/action/admin/indices/shrink/TransportResizeActionTests.java index b830c6b01792c..ef49820192e9b 100644 --- a/server/src/test/java/org/opensearch/action/admin/indices/shrink/TransportResizeActionTests.java +++ b/server/src/test/java/org/opensearch/action/admin/indices/shrink/TransportResizeActionTests.java @@ -470,6 +470,97 @@ public void testCalculateTargetIndexShardsNum() { ); } + public void testIndexBlocks() { + String indexName = randomAlphaOfLength(10); + // create one that won't fail + ClusterState clusterState = ClusterState.builder( + createClusterState(indexName, 10, 0, 40, Settings.builder().put("index.blocks.read_only", true).build()) + ).nodes(DiscoveryNodes.builder().add(newNode("node1"))).build(); + + // Target index will be blocked by [index.blocks.read_only=true] copied from the source index + ResizeRequest resizeRequest = new ResizeRequest("target", indexName); + ResizeType resizeType; + switch (randomIntBetween(0, 2)) { + case 0: + resizeType = ResizeType.SHRINK; + break; + case 1: + resizeType = ResizeType.SPLIT; + break; + default: + resizeType = ResizeType.CLONE; + } + resizeRequest.setResizeType(resizeType); + resizeRequest.getTargetIndexRequest().settings(Settings.builder().put("index.number_of_shards", randomIntBetween(1, 100)).build()); + ClusterState finalState = clusterState; + IllegalArgumentException iae = expectThrows( + IllegalArgumentException.class, + () -> TransportResizeAction.prepareCreateIndexRequest( + resizeRequest, + finalState, + null, + new StoreStats(between(1, 10000), between(1, 10000)), + indexName, + "target" + ) + ); + assertEquals( + "target index [target] will be blocked by [index.blocks.read_only=true] which is copied from the source index [" + + indexName + + "], this will disable metadata writes and cause the shards to be unassigned", + iae.getMessage() + ); + + // Overwrites the source index's settings index.blocks.read_only, so resize won't fail + AllocationService service = new AllocationService( + new AllocationDeciders(Collections.singleton(new MaxRetryAllocationDecider())), + new TestGatewayAllocator(), + new BalancedShardsAllocator(Settings.EMPTY), + EmptyClusterInfoService.INSTANCE, + EmptySnapshotsInfoService.INSTANCE + ); + RoutingTable routingTable = service.reroute(clusterState, "reroute").routingTable(); + clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); + // now we start the shard + routingTable = OpenSearchAllocationTestCase.startInitializingShardsAndReroute(service, clusterState, indexName).routingTable(); + clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); + int numSourceShards = clusterState.metadata().index(indexName).getNumberOfShards(); + DocsStats stats = new DocsStats(between(0, (IndexWriter.MAX_DOCS) / numSourceShards), between(1, 1000), between(1, 10000)); + + int expectedShardsNum; + String cause; + switch (resizeType) { + case SHRINK: + expectedShardsNum = 5; + cause = "shrink_index"; + break; + case SPLIT: + expectedShardsNum = 20; + cause = "split_index"; + break; + default: + expectedShardsNum = 10; + cause = "clone_index"; + } + resizeRequest.getTargetIndexRequest() + .settings(Settings.builder().put("index.number_of_shards", expectedShardsNum).put("index.blocks.read_only", false).build()); + final ActiveShardCount activeShardCount = randomBoolean() ? ActiveShardCount.ALL : ActiveShardCount.ONE; + resizeRequest.setWaitForActiveShards(activeShardCount); + CreateIndexClusterStateUpdateRequest request = TransportResizeAction.prepareCreateIndexRequest( + resizeRequest, + clusterState, + (i) -> stats, + new StoreStats(100, between(1, 10000)), + indexName, + "target" + ); + assertNotNull(request.recoverFrom()); + assertEquals(indexName, request.recoverFrom().getName()); + assertEquals(String.valueOf(expectedShardsNum), request.settings().get("index.number_of_shards")); + assertEquals(cause, request.cause()); + assertEquals(request.waitForActiveShards(), activeShardCount); + } + private DiscoveryNode newNode(String nodeId) { final Set roles = Collections.unmodifiableSet( new HashSet<>(Arrays.asList(DiscoveryNodeRole.CLUSTER_MANAGER_ROLE, DiscoveryNodeRole.DATA_ROLE)) diff --git a/server/src/test/java/org/opensearch/cluster/metadata/IndexMetadataTests.java b/server/src/test/java/org/opensearch/cluster/metadata/IndexMetadataTests.java index 59a16f07a6ac9..38fb1a657b9e8 100644 --- a/server/src/test/java/org/opensearch/cluster/metadata/IndexMetadataTests.java +++ b/server/src/test/java/org/opensearch/cluster/metadata/IndexMetadataTests.java @@ -228,6 +228,25 @@ public void testSelectShrinkShards() { ); } + public void testSelectCloneShard() { + int numberOfReplicas = randomIntBetween(0, 10); + IndexMetadata metadata = IndexMetadata.builder("foo") + .settings( + Settings.builder() + .put("index.version.created", 1) + .put("index.number_of_shards", 10) + .put("index.number_of_replicas", numberOfReplicas) + .build() + ) + .creationDate(randomLong()) + .build(); + + assertEquals( + "the number of target shards (11) must be the same as the number of source shards (10)", + expectThrows(IllegalArgumentException.class, () -> IndexMetadata.selectCloneShard(0, metadata, 11)).getMessage() + ); + } + public void testSelectResizeShards() { int numTargetShards = randomFrom(4, 6, 8, 12); diff --git a/server/src/test/java/org/opensearch/cluster/metadata/MetadataCreateIndexServiceTests.java b/server/src/test/java/org/opensearch/cluster/metadata/MetadataCreateIndexServiceTests.java index 74b294709f95f..00d496fde0434 100644 --- a/server/src/test/java/org/opensearch/cluster/metadata/MetadataCreateIndexServiceTests.java +++ b/server/src/test/java/org/opensearch/cluster/metadata/MetadataCreateIndexServiceTests.java @@ -275,7 +275,7 @@ public void testValidateShrinkIndex() { ); assertEquals( - "index source must be read-only to resize index. use \"index.blocks.write=true\"", + "index source must block write operations to resize index. use \"index.blocks.write=true\"", expectThrows( IllegalStateException.class, () -> MetadataCreateIndexService.validateShrinkIndex( @@ -377,7 +377,7 @@ public void testValidateSplitIndex() { ); assertEquals( - "index source must be read-only to resize index. use \"index.blocks.write=true\"", + "index source must block write operations to resize index. use \"index.blocks.write=true\"", expectThrows( IllegalStateException.class, () -> MetadataCreateIndexService.validateSplitIndex( @@ -436,6 +436,65 @@ public void testValidateSplitIndex() { ); } + public void testValidateCloneIndex() { + int numShards = randomIntBetween(1, 42); + Settings targetSettings = Settings.builder().put("index.number_of_shards", numShards).build(); + ClusterState state = createClusterState( + "source", + numShards, + randomIntBetween(0, 10), + Settings.builder().put("index.blocks.write", true).build() + ); + + assertEquals( + "index [source] already exists", + expectThrows( + ResourceAlreadyExistsException.class, + () -> MetadataCreateIndexService.validateCloneIndex(state, "target", "source", targetSettings) + ).getMessage() + ); + + assertEquals( + "no such index [no_such_index]", + expectThrows( + IndexNotFoundException.class, + () -> MetadataCreateIndexService.validateCloneIndex(state, "no_such_index", "target", targetSettings) + ).getMessage() + ); + + assertEquals( + "index source must block write operations to resize index. use \"index.blocks.write=true\"", + expectThrows( + IllegalStateException.class, + () -> MetadataCreateIndexService.validateCloneIndex( + createClusterState("source", randomIntBetween(2, 100), randomIntBetween(0, 10), Settings.EMPTY), + "source", + "target", + targetSettings + ) + ).getMessage() + ); + + ClusterState clusterState = ClusterState.builder( + createClusterState("source", numShards, 0, Settings.builder().put("index.blocks.write", true).build()) + ).nodes(DiscoveryNodes.builder().add(newNode("node1"))).build(); + AllocationService service = new AllocationService( + new AllocationDeciders(singleton(new MaxRetryAllocationDecider())), + new TestGatewayAllocator(), + new BalancedShardsAllocator(Settings.EMPTY), + EmptyClusterInfoService.INSTANCE, + EmptySnapshotsInfoService.INSTANCE + ); + + RoutingTable routingTable = service.reroute(clusterState, "reroute").routingTable(); + clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); + // now we start the shard + routingTable = OpenSearchAllocationTestCase.startInitializingShardsAndReroute(service, clusterState, "source").routingTable(); + clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); + + MetadataCreateIndexService.validateCloneIndex(clusterState, "source", "target", targetSettings); + } + public void testPrepareResizeIndexSettings() { final List versions = Arrays.asList(VersionUtils.randomVersion(random()), VersionUtils.randomVersion(random())); versions.sort(Comparator.comparingLong(l -> l.id));