From 0aff606b357dd492735ec9bbbced6e309de54387 Mon Sep 17 00:00:00 2001 From: Albert Zaharovits Date: Wed, 4 Sep 2024 09:47:54 +0300 Subject: [PATCH] Avoid passing in the cluster state parameter to methods related to index creation (#112466) Avoids the ClusterState type as a method parameter in favor of the more specific Metadata, RoutingTable, and ClusterBlocks ones. --- .../indices/rollover/LazyRolloverAction.java | 3 +- .../rollover/MetadataRolloverService.java | 10 +-- .../rollover/TransportRolloverAction.java | 3 +- .../metadata/MetadataCreateIndexService.java | 89 +++++++++++++------ .../metadata/MetadataIndexStateService.java | 2 +- .../MetadataUpdateSettingsService.java | 7 +- .../ShardsCapacityHealthIndicatorService.java | 36 ++++++-- .../indices/ShardLimitValidator.java | 84 +++++++++-------- .../snapshots/RestoreService.java | 17 +++- .../MetadataCreateIndexServiceTests.java | 76 ++++++++-------- ...dsCapacityHealthIndicatorServiceTests.java | 18 ++-- .../indices/ShardLimitValidatorTests.java | 25 ++++-- .../downsample/TransportDownsampleAction.java | 2 +- 13 files changed, 235 insertions(+), 137 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/LazyRolloverAction.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/LazyRolloverAction.java index ef72fdd93caeb..65b768a1c629f 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/LazyRolloverAction.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/LazyRolloverAction.java @@ -21,6 +21,7 @@ import org.elasticsearch.cluster.metadata.DataStream; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.Metadata; +import org.elasticsearch.cluster.metadata.MetadataCreateIndexService; import org.elasticsearch.cluster.metadata.MetadataDataStreamsService; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.allocator.AllocationActionMultiListener; @@ -134,7 +135,7 @@ protected void masterOperation( ); final String trialSourceIndexName = trialRolloverNames.sourceName(); final String trialRolloverIndexName = trialRolloverNames.rolloverName(); - MetadataRolloverService.validateIndexName(clusterState, trialRolloverIndexName); + MetadataCreateIndexService.validateIndexName(trialRolloverIndexName, clusterState.metadata(), clusterState.routingTable()); assert metadata.dataStreams().containsKey(rolloverRequest.getRolloverTarget()) : "Auto-rollover applies only to data streams"; diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MetadataRolloverService.java b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MetadataRolloverService.java index 9d34b9ab5f126..b8d975f82980d 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MetadataRolloverService.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/rollover/MetadataRolloverService.java @@ -179,10 +179,6 @@ public RolloverResult rolloverClusterState( }; } - public static void validateIndexName(ClusterState state, String index) { - MetadataCreateIndexService.validateIndexName(index, state); - } - /** * Returns the names that rollover would use, but does not perform the actual rollover */ @@ -252,7 +248,8 @@ private RolloverResult rolloverAlias( final Boolean isHidden = IndexMetadata.INDEX_HIDDEN_SETTING.exists(createIndexRequest.settings()) ? IndexMetadata.INDEX_HIDDEN_SETTING.get(createIndexRequest.settings()) : null; - MetadataCreateIndexService.validateIndexName(rolloverIndexName, currentState); // fails if the index already exists + MetadataCreateIndexService.validateIndexName(rolloverIndexName, metadata, currentState.routingTable()); // fails if the index + // already exists checkNoDuplicatedAliasInIndexTemplate(metadata, rolloverIndexName, aliasName, isHidden); if (onlyValidate) { return new RolloverResult(rolloverIndexName, sourceIndexName, currentState); @@ -328,7 +325,8 @@ private RolloverResult rolloverDataStream( final Tuple nextIndexAndGeneration = dataStream.nextWriteIndexAndGeneration(metadata, dataStreamIndices); final String newWriteIndexName = nextIndexAndGeneration.v1(); final long newGeneration = nextIndexAndGeneration.v2(); - MetadataCreateIndexService.validateIndexName(newWriteIndexName, currentState); // fails if the index already exists + MetadataCreateIndexService.validateIndexName(newWriteIndexName, metadata, currentState.routingTable()); // fails if the index + // already exists if (onlyValidate) { return new RolloverResult(newWriteIndexName, isLazyCreation ? NON_EXISTENT_SOURCE : originalWriteIndex.getName(), currentState); } 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 9df3be1994fdf..c997795bb3b89 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 @@ -36,6 +36,7 @@ import org.elasticsearch.cluster.metadata.IndexMetadataStats; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.Metadata; +import org.elasticsearch.cluster.metadata.MetadataCreateIndexService; import org.elasticsearch.cluster.metadata.MetadataDataStreamsService; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.allocator.AllocationActionMultiListener; @@ -179,7 +180,7 @@ protected void masterOperation( ); final String trialSourceIndexName = trialRolloverNames.sourceName(); final String trialRolloverIndexName = trialRolloverNames.rolloverName(); - MetadataRolloverService.validateIndexName(clusterState, trialRolloverIndexName); + MetadataCreateIndexService.validateIndexName(trialRolloverIndexName, metadata, clusterState.routingTable()); boolean isDataStream = metadata.dataStreams().containsKey(rolloverRequest.getRolloverTarget()); if (rolloverRequest.isLazy()) { diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java index 07dcb7baf0777..02b7312b4a99d 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java @@ -167,7 +167,7 @@ public MetadataCreateIndexService( /** * Validate the name for an index against some static rules and a cluster state. */ - public static void validateIndexName(String index, ClusterState state) { + public static void validateIndexName(String index, Metadata metadata, RoutingTable routingTable) { validateIndexOrAliasName(index, InvalidIndexNameException::new); if (index.toLowerCase(Locale.ROOT).equals(index) == false) { throw new InvalidIndexNameException(index, "must be lowercase"); @@ -175,13 +175,13 @@ public static void validateIndexName(String index, ClusterState state) { // NOTE: dot-prefixed index names are validated after template application, not here - if (state.routingTable().hasIndex(index)) { - throw new ResourceAlreadyExistsException(state.routingTable().index(index).getIndex()); + if (routingTable.hasIndex(index)) { + throw new ResourceAlreadyExistsException(routingTable.index(index).getIndex()); } - if (state.metadata().hasIndex(index)) { - throw new ResourceAlreadyExistsException(state.metadata().index(index).getIndex()); + if (metadata.hasIndex(index)) { + throw new ResourceAlreadyExistsException(metadata.index(index).getIndex()); } - if (state.metadata().hasAlias(index)) { + if (metadata.hasAlias(index)) { throw new InvalidIndexNameException(index, "already exists as alias"); } } @@ -344,7 +344,7 @@ public ClusterState applyCreateIndexRequest( normalizeRequestSetting(request); logger.trace("executing IndexCreationTask for [{}] against cluster state version [{}]", request, currentState.version()); - validate(request, currentState); + validate(request, currentState.metadata(), currentState.routingTable()); final Index recoverFromIndex = request.recoverFrom(); final IndexMetadata sourceMetadata = recoverFromIndex == null ? null : currentState.metadata().getIndexSafe(recoverFromIndex); @@ -1069,7 +1069,9 @@ static Settings aggregateIndexSettings( if (sourceMetadata != null) { assert request.resizeType() != null; prepareResizeIndexSettings( - currentState, + currentState.metadata(), + currentState.blocks(), + currentState.routingTable(), indexSettingsBuilder, request.recoverFrom(), request.index(), @@ -1084,7 +1086,7 @@ static Settings aggregateIndexSettings( * We can not validate settings until we have applied templates, otherwise we do not know the actual settings * that will be used to create this index. */ - shardLimitValidator.validateShardLimit(indexSettings, currentState); + shardLimitValidator.validateShardLimit(indexSettings, currentState.nodes(), currentState.metadata()); validateSoftDeleteSettings(indexSettings); validateTranslogRetentionSettings(indexSettings); validateStoreTypeSetting(indexSettings); @@ -1363,8 +1365,8 @@ private static void validateActiveShardCount(ActiveShardCount waitForActiveShard } } - private void validate(CreateIndexClusterStateUpdateRequest request, ClusterState state) { - validateIndexName(request.index(), state); + private void validate(CreateIndexClusterStateUpdateRequest request, Metadata metadata, RoutingTable routingTable) { + validateIndexName(request.index(), metadata, routingTable); validateIndexSettings(request.index(), request.settings(), forbidPrivateIndexSettings); } @@ -1428,8 +1430,15 @@ private static List validateIndexCustomPath(Settings settings, @Nullable * * @return the list of nodes at least one instance of the source index shards are allocated */ - static List validateShrinkIndex(ClusterState state, String sourceIndex, String targetIndexName, Settings targetIndexSettings) { - IndexMetadata sourceMetadata = validateResize(state, sourceIndex, targetIndexName, targetIndexSettings); + static List validateShrinkIndex( + Metadata metadata, + ClusterBlocks clusterBlocks, + RoutingTable routingTable, + String sourceIndex, + String targetIndexName, + Settings targetIndexSettings + ) { + IndexMetadata sourceMetadata = validateResize(metadata, clusterBlocks, sourceIndex, targetIndexName, targetIndexSettings); if (sourceMetadata.isSearchableSnapshot()) { throw new IllegalArgumentException("can't shrink searchable snapshot index [" + sourceIndex + ']'); } @@ -1441,7 +1450,7 @@ static List validateShrinkIndex(ClusterState state, String sourceIndex, } // now check that index is all on one node - final IndexRoutingTable table = state.routingTable().index(sourceIndex); + final IndexRoutingTable table = routingTable.index(sourceIndex); Map nodesToNumRouting = new HashMap<>(); int numShards = sourceMetadata.getNumberOfShards(); for (ShardRouting routing : table.shardsWithState(ShardRoutingState.STARTED)) { @@ -1461,16 +1470,28 @@ static List validateShrinkIndex(ClusterState state, String sourceIndex, return nodesToAllocateOn; } - static void validateSplitIndex(ClusterState state, String sourceIndex, String targetIndexName, Settings targetIndexSettings) { - IndexMetadata sourceMetadata = validateResize(state, sourceIndex, targetIndexName, targetIndexSettings); + static void validateSplitIndex( + Metadata metadata, + ClusterBlocks clusterBlocks, + String sourceIndex, + String targetIndexName, + Settings targetIndexSettings + ) { + IndexMetadata sourceMetadata = validateResize(metadata, clusterBlocks, sourceIndex, targetIndexName, targetIndexSettings); if (sourceMetadata.isSearchableSnapshot()) { throw new IllegalArgumentException("can't split searchable snapshot index [" + sourceIndex + ']'); } IndexMetadata.selectSplitShard(0, sourceMetadata, INDEX_NUMBER_OF_SHARDS_SETTING.get(targetIndexSettings)); } - static void validateCloneIndex(ClusterState state, String sourceIndex, String targetIndexName, Settings targetIndexSettings) { - IndexMetadata sourceMetadata = validateResize(state, sourceIndex, targetIndexName, targetIndexSettings); + static void validateCloneIndex( + Metadata metadata, + ClusterBlocks clusterBlocks, + String sourceIndex, + String targetIndexName, + Settings targetIndexSettings + ) { + IndexMetadata sourceMetadata = validateResize(metadata, clusterBlocks, sourceIndex, targetIndexName, targetIndexSettings); if (sourceMetadata.isSearchableSnapshot()) { for (Setting nonCloneableSetting : Arrays.asList(INDEX_STORE_TYPE_SETTING, INDEX_RECOVERY_TYPE_SETTING)) { if (nonCloneableSetting.exists(targetIndexSettings) == false) { @@ -1487,16 +1508,22 @@ static void validateCloneIndex(ClusterState state, String sourceIndex, String ta IndexMetadata.selectCloneShard(0, sourceMetadata, INDEX_NUMBER_OF_SHARDS_SETTING.get(targetIndexSettings)); } - static IndexMetadata validateResize(ClusterState state, String sourceIndex, String targetIndexName, Settings targetIndexSettings) { - if (state.metadata().hasIndex(targetIndexName)) { - throw new ResourceAlreadyExistsException(state.metadata().index(targetIndexName).getIndex()); + static IndexMetadata validateResize( + Metadata metadata, + ClusterBlocks clusterBlocks, + String sourceIndex, + String targetIndexName, + Settings targetIndexSettings + ) { + if (metadata.hasIndex(targetIndexName)) { + throw new ResourceAlreadyExistsException(metadata.index(targetIndexName).getIndex()); } - final IndexMetadata sourceMetadata = state.metadata().index(sourceIndex); + final IndexMetadata sourceMetadata = metadata.index(sourceIndex); if (sourceMetadata == null) { throw new IndexNotFoundException(sourceIndex); } - IndexAbstraction source = state.metadata().getIndicesLookup().get(sourceIndex); + IndexAbstraction source = metadata.getIndicesLookup().get(sourceIndex); assert source != null; if (source.getParentDataStream() != null && source.getParentDataStream().getWriteIndex().equals(sourceMetadata.getIndex())) { throw new IllegalArgumentException( @@ -1509,7 +1536,7 @@ static IndexMetadata validateResize(ClusterState state, String sourceIndex, Stri ); } // ensure index is read-only - if (state.blocks().indexBlocked(ClusterBlockLevel.WRITE, sourceIndex) == false) { + if (clusterBlocks.indexBlocked(ClusterBlockLevel.WRITE, sourceIndex) == false) { throw new IllegalStateException("index " + sourceIndex + " must be read-only to resize index. use \"index.blocks.write=true\""); } @@ -1522,7 +1549,9 @@ static IndexMetadata validateResize(ClusterState state, String sourceIndex, Stri } static void prepareResizeIndexSettings( - final ClusterState currentState, + final Metadata metadata, + final ClusterBlocks clusterBlocks, + final RoutingTable routingTable, final Settings.Builder indexSettingsBuilder, final Index resizeSourceIndex, final String resizeIntoName, @@ -1530,20 +1559,22 @@ static void prepareResizeIndexSettings( final boolean copySettings, final IndexScopedSettings indexScopedSettings ) { - final IndexMetadata sourceMetadata = currentState.metadata().index(resizeSourceIndex.getName()); + final IndexMetadata sourceMetadata = metadata.index(resizeSourceIndex.getName()); if (type == ResizeType.SHRINK) { final List nodesToAllocateOn = validateShrinkIndex( - currentState, + metadata, + clusterBlocks, + routingTable, resizeSourceIndex.getName(), resizeIntoName, indexSettingsBuilder.build() ); indexSettingsBuilder.put(INDEX_SHRINK_INITIAL_RECOVERY_KEY, Strings.arrayToCommaDelimitedString(nodesToAllocateOn.toArray())); } else if (type == ResizeType.SPLIT) { - validateSplitIndex(currentState, resizeSourceIndex.getName(), resizeIntoName, indexSettingsBuilder.build()); + validateSplitIndex(metadata, clusterBlocks, resizeSourceIndex.getName(), resizeIntoName, indexSettingsBuilder.build()); indexSettingsBuilder.putNull(INDEX_SHRINK_INITIAL_RECOVERY_KEY); } else if (type == ResizeType.CLONE) { - validateCloneIndex(currentState, resizeSourceIndex.getName(), resizeIntoName, indexSettingsBuilder.build()); + validateCloneIndex(metadata, clusterBlocks, resizeSourceIndex.getName(), resizeIntoName, indexSettingsBuilder.build()); indexSettingsBuilder.putNull(INDEX_SHRINK_INITIAL_RECOVERY_KEY); } else { throw new IllegalStateException("unknown resize type is " + type); diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexStateService.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexStateService.java index be12198cbaaaa..272c107883043 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexStateService.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexStateService.java @@ -1100,7 +1100,7 @@ private ClusterState openIndices(final Index[] indices, final ClusterState curre } } - shardLimitValidator.validateShardLimit(currentState, indices); + shardLimitValidator.validateShardLimit(currentState.nodes(), currentState.metadata(), indices); if (indicesToOpen.isEmpty()) { return currentState; } diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataUpdateSettingsService.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataUpdateSettingsService.java index 5891b953acfca..3272462dd3725 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataUpdateSettingsService.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetadataUpdateSettingsService.java @@ -255,7 +255,12 @@ ClusterState execute(ClusterState currentState) { final int updatedNumberOfReplicas = IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING.get(openSettings); if (preserveExisting == false) { // Verify that this won't take us over the cluster shard limit. - shardLimitValidator.validateShardLimitOnReplicaUpdate(currentState, request.indices(), updatedNumberOfReplicas); + shardLimitValidator.validateShardLimitOnReplicaUpdate( + currentState.nodes(), + currentState.metadata(), + request.indices(), + updatedNumberOfReplicas + ); /* * We do not update the in-sync allocation IDs as they will be removed upon the first index operation diff --git a/server/src/main/java/org/elasticsearch/health/node/ShardsCapacityHealthIndicatorService.java b/server/src/main/java/org/elasticsearch/health/node/ShardsCapacityHealthIndicatorService.java index e5ced00905744..e591e8a681764 100644 --- a/server/src/main/java/org/elasticsearch/health/node/ShardsCapacityHealthIndicatorService.java +++ b/server/src/main/java/org/elasticsearch/health/node/ShardsCapacityHealthIndicatorService.java @@ -8,7 +8,8 @@ package org.elasticsearch.health.node; -import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.metadata.Metadata; +import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.TriFunction; import org.elasticsearch.common.settings.Setting; @@ -124,8 +125,18 @@ public HealthIndicatorResult calculate(boolean verbose, int maxAffectedResources var shardLimitsMetadata = healthMetadata.getShardLimitsMetadata(); return mergeIndicators( verbose, - calculateFrom(shardLimitsMetadata.maxShardsPerNode(), state, ShardLimitValidator::checkShardLimitForNormalNodes), - calculateFrom(shardLimitsMetadata.maxShardsPerNodeFrozen(), state, ShardLimitValidator::checkShardLimitForFrozenNodes) + calculateFrom( + shardLimitsMetadata.maxShardsPerNode(), + state.nodes(), + state.metadata(), + ShardLimitValidator::checkShardLimitForNormalNodes + ), + calculateFrom( + shardLimitsMetadata.maxShardsPerNodeFrozen(), + state.nodes(), + state.metadata(), + ShardLimitValidator::checkShardLimitForFrozenNodes + ) ); } @@ -173,13 +184,18 @@ private HealthIndicatorResult mergeIndicators(boolean verbose, StatusResult data ); } - static StatusResult calculateFrom(int maxShardsPerNodeSetting, ClusterState state, ShardsCapacityChecker checker) { - var result = checker.check(maxShardsPerNodeSetting, 5, 1, state); + static StatusResult calculateFrom( + int maxShardsPerNodeSetting, + DiscoveryNodes discoveryNodes, + Metadata metadata, + ShardsCapacityChecker checker + ) { + var result = checker.check(maxShardsPerNodeSetting, 5, 1, discoveryNodes, metadata); if (result.canAddShards() == false) { return new StatusResult(HealthStatus.RED, result); } - result = checker.check(maxShardsPerNodeSetting, 10, 1, state); + result = checker.check(maxShardsPerNodeSetting, 10, 1, discoveryNodes, metadata); if (result.canAddShards() == false) { return new StatusResult(HealthStatus.YELLOW, result); } @@ -225,6 +241,12 @@ record StatusResult(HealthStatus status, ShardLimitValidator.Result result) {} @FunctionalInterface interface ShardsCapacityChecker { - ShardLimitValidator.Result check(int maxConfiguredShardsPerNode, int numberOfNewShards, int replicas, ClusterState state); + ShardLimitValidator.Result check( + int maxConfiguredShardsPerNode, + int numberOfNewShards, + int replicas, + DiscoveryNodes discoveryNodes, + Metadata metadata + ); } } diff --git a/server/src/main/java/org/elasticsearch/indices/ShardLimitValidator.java b/server/src/main/java/org/elasticsearch/indices/ShardLimitValidator.java index f58ee757cc511..b8841adb4d885 100644 --- a/server/src/main/java/org/elasticsearch/indices/ShardLimitValidator.java +++ b/server/src/main/java/org/elasticsearch/indices/ShardLimitValidator.java @@ -8,10 +8,11 @@ package org.elasticsearch.indices; -import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetadata; +import org.elasticsearch.cluster.metadata.Metadata; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodeRole; +import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.ReferenceDocs; import org.elasticsearch.common.ValidationException; @@ -95,16 +96,22 @@ public int getShardLimitPerNode() { * Checks whether an index can be created without going over the cluster shard limit. * * @param settings the settings of the index to be created - * @param state the current cluster state + * @param discoveryNodes the nodes in the cluster + * @param metadata the cluster state metadata * @throws ValidationException if creating this index would put the cluster over the cluster shard limit */ - public void validateShardLimit(final Settings settings, final ClusterState state) { + public void validateShardLimit(final Settings settings, final DiscoveryNodes discoveryNodes, final Metadata metadata) { final int numberOfShards = INDEX_NUMBER_OF_SHARDS_SETTING.get(settings); final int numberOfReplicas = IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING.get(settings); final int shardsToCreate = numberOfShards * (1 + numberOfReplicas); final boolean frozen = FROZEN_GROUP.equals(INDEX_SETTING_SHARD_LIMIT_GROUP.get(settings)); - final var result = checkShardLimitOnBothGroups(frozen == false ? shardsToCreate : 0, frozen ? shardsToCreate : 0, state); + final var result = checkShardLimitOnBothGroups( + frozen == false ? shardsToCreate : 0, + frozen ? shardsToCreate : 0, + discoveryNodes, + metadata + ); if (result.canAddShards == false) { final ValidationException e = new ValidationException(); e.addValidationError(errorMessageFrom(result)); @@ -116,15 +123,16 @@ public void validateShardLimit(final Settings settings, final ClusterState state * Validates whether a list of indices can be opened without going over the cluster shard limit. Only counts indices which are * currently closed and will be opened, ignores indices which are already open. * - * @param currentState The current cluster state. - * @param indicesToOpen The indices which are to be opened. + * @param discoveryNodes The nodes in the cluster + * @param metadata The cluster state metadata + * @param indicesToOpen The indices which are to be opened. * @throws ValidationException If this operation would take the cluster over the limit and enforcement is enabled. */ - public void validateShardLimit(ClusterState currentState, Index[] indicesToOpen) { + public void validateShardLimit(DiscoveryNodes discoveryNodes, Metadata metadata, Index[] indicesToOpen) { int frozen = 0; int normal = 0; for (Index index : indicesToOpen) { - IndexMetadata imd = currentState.metadata().index(index); + IndexMetadata imd = metadata.index(index); if (imd.getState().equals(IndexMetadata.State.CLOSE)) { int totalNewShards = imd.getNumberOfShards() * (1 + imd.getNumberOfReplicas()); if (FROZEN_GROUP.equals(INDEX_SETTING_SHARD_LIMIT_GROUP.get(imd.getSettings()))) { @@ -135,7 +143,7 @@ public void validateShardLimit(ClusterState currentState, Index[] indicesToOpen) } } - var result = checkShardLimitOnBothGroups(normal, frozen, currentState); + var result = checkShardLimitOnBothGroups(normal, frozen, discoveryNodes, metadata); if (result.canAddShards == false) { ValidationException ex = new ValidationException(); ex.addValidationError(errorMessageFrom(result)); @@ -143,12 +151,12 @@ public void validateShardLimit(ClusterState currentState, Index[] indicesToOpen) } } - public void validateShardLimitOnReplicaUpdate(ClusterState currentState, Index[] indices, int replicas) { + public void validateShardLimitOnReplicaUpdate(DiscoveryNodes discoveryNodes, Metadata metadata, Index[] indices, int replicas) { int frozen = 0; int normal = 0; for (Index index : indices) { - IndexMetadata imd = currentState.metadata().index(index); - int totalNewShards = getTotalNewShards(index, currentState, replicas); + IndexMetadata imd = metadata.index(index); + int totalNewShards = getTotalNewShards(index, metadata, replicas); if (FROZEN_GROUP.equals(INDEX_SETTING_SHARD_LIMIT_GROUP.get(imd.getSettings()))) { frozen += totalNewShards; } else { @@ -156,7 +164,7 @@ public void validateShardLimitOnReplicaUpdate(ClusterState currentState, Index[] } } - var result = checkShardLimitOnBothGroups(normal, frozen, currentState); + var result = checkShardLimitOnBothGroups(normal, frozen, discoveryNodes, metadata); if (result.canAddShards == false) { ValidationException ex = new ValidationException(); ex.addValidationError(errorMessageFrom(result)); @@ -164,8 +172,8 @@ public void validateShardLimitOnReplicaUpdate(ClusterState currentState, Index[] } } - private static int getTotalNewShards(Index index, ClusterState currentState, int updatedNumberOfReplicas) { - IndexMetadata indexMetadata = currentState.metadata().index(index); + private static int getTotalNewShards(Index index, Metadata metadata, int updatedNumberOfReplicas) { + IndexMetadata indexMetadata = metadata.index(index); int shardsInIndex = indexMetadata.getNumberOfShards(); int oldNumberOfReplicas = indexMetadata.getNumberOfReplicas(); int replicaIncrease = updatedNumberOfReplicas - oldNumberOfReplicas; @@ -181,21 +189,22 @@ private static int getTotalNewShards(Index index, ClusterState currentState, int * * @param newShards The number of normal shards to be added by this operation * @param newFrozenShards The number of frozen shards to be added by this operation - * @param state The current cluster state + * @param discoveryNodes The nodes in the cluster + * @param metadata The cluster state metadata */ - private Result checkShardLimitOnBothGroups(int newShards, int newFrozenShards, ClusterState state) { + private Result checkShardLimitOnBothGroups(int newShards, int newFrozenShards, DiscoveryNodes discoveryNodes, Metadata metadata) { // we verify the two limits independently. This also means that if they have mixed frozen and other data-roles nodes, such a mixed // node can have both 1000 normal and 3000 frozen shards. This is the trade-off to keep the simplicity of the counts. We advocate // against such mixed nodes for production use anyway. - int frozenNodeCount = nodeCount(state, ShardLimitValidator::hasFrozen); - int normalNodeCount = nodeCount(state, ShardLimitValidator::hasNonFrozen); + int frozenNodeCount = nodeCount(discoveryNodes, ShardLimitValidator::hasFrozen); + int normalNodeCount = nodeCount(discoveryNodes, ShardLimitValidator::hasNonFrozen); - var result = checkShardLimit(newShards, state, getShardLimitPerNode(), normalNodeCount, NORMAL_GROUP); + var result = checkShardLimit(newShards, metadata, getShardLimitPerNode(), normalNodeCount, NORMAL_GROUP); // fail-fast: in case there's no room on the `normal` nodes, just return the result of that check. if (result.canAddShards() == false) { return result; } - return checkShardLimit(newFrozenShards, state, shardLimitPerNodeFrozen.get(), frozenNodeCount, FROZEN_GROUP); + return checkShardLimit(newFrozenShards, metadata, shardLimitPerNodeFrozen.get(), frozenNodeCount, FROZEN_GROUP); } /** @@ -205,20 +214,21 @@ private Result checkShardLimitOnBothGroups(int newShards, int newFrozenShards, C * @param maxConfiguredShardsPerNode The maximum available number of shards to be allocated within a node * @param numberOfNewShards The number of primary shards that we want to be able to add to the cluster * @param replicas The number of replicas of the primary shards that we want to be able to add to the cluster - * @param state The cluster state, used to get cluster settings and to get the number of open shards already in - * the cluster + * @param discoveryNodes The nodes in the cluster, used to get the number of open shard already in the cluster + * @param metadata The cluster state metadata, used to get the cluster settings */ public static Result checkShardLimitForNormalNodes( int maxConfiguredShardsPerNode, int numberOfNewShards, int replicas, - ClusterState state + DiscoveryNodes discoveryNodes, + Metadata metadata ) { return checkShardLimit( numberOfNewShards * (1 + replicas), - state, + metadata, maxConfiguredShardsPerNode, - nodeCount(state, ShardLimitValidator::hasNonFrozen), + nodeCount(discoveryNodes, ShardLimitValidator::hasNonFrozen), NORMAL_GROUP ); } @@ -230,27 +240,28 @@ public static Result checkShardLimitForNormalNodes( * @param maxConfiguredShardsPerNode The maximum available number of shards to be allocated within a node * @param numberOfNewShards The number of primary shards that we want to be able to add to the cluster * @param replicas The number of replicas of the primary shards that we want to be able to add to the cluster - * @param state The cluster state, used to get cluster settings and to get the number of open shards already in - * the cluster + * @param discoveryNodes The nodes in the cluster, used to get the number of open shard already in the cluster + * @param metadata The cluster state metadata, used to get the cluster settings */ public static Result checkShardLimitForFrozenNodes( int maxConfiguredShardsPerNode, int numberOfNewShards, int replicas, - ClusterState state + DiscoveryNodes discoveryNodes, + Metadata metadata ) { return checkShardLimit( numberOfNewShards * (1 + replicas), - state, + metadata, maxConfiguredShardsPerNode, - nodeCount(state, ShardLimitValidator::hasFrozen), + nodeCount(discoveryNodes, ShardLimitValidator::hasFrozen), FROZEN_GROUP ); } - private static Result checkShardLimit(int newShards, ClusterState state, int maxConfiguredShardsPerNode, int nodeCount, String group) { + private static Result checkShardLimit(int newShards, Metadata metadata, int maxConfiguredShardsPerNode, int nodeCount, String group) { int maxShardsInCluster = maxConfiguredShardsPerNode * nodeCount; - int currentOpenShards = state.getMetadata().getTotalOpenIndexShards(); + int currentOpenShards = metadata.getTotalOpenIndexShards(); // Only enforce the shard limit if we have at least one data node, so that we don't block // index creation during cluster setup @@ -261,8 +272,7 @@ private static Result checkShardLimit(int newShards, ClusterState state, int max if ((currentOpenShards + newShards) > maxShardsInCluster) { Predicate indexMetadataPredicate = imd -> imd.getState().equals(IndexMetadata.State.OPEN) && group.equals(INDEX_SETTING_SHARD_LIMIT_GROUP.get(imd.getSettings())); - long currentFilteredShards = state.metadata() - .indices() + long currentFilteredShards = metadata.indices() .values() .stream() .filter(indexMetadataPredicate) @@ -276,8 +286,8 @@ private static Result checkShardLimit(int newShards, ClusterState state, int max return new Result(true, Optional.empty(), newShards, maxShardsInCluster, group); } - private static int nodeCount(ClusterState state, Predicate nodePredicate) { - return (int) state.getNodes().getDataNodes().values().stream().filter(nodePredicate).count(); + private static int nodeCount(DiscoveryNodes discoveryNodes, Predicate nodePredicate) { + return (int) discoveryNodes.getDataNodes().values().stream().filter(nodePredicate).count(); } private static boolean hasFrozen(DiscoveryNode node) { diff --git a/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java b/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java index d8987495f9035..a2d8d6374a457 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java +++ b/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java @@ -1343,8 +1343,12 @@ public ClusterState execute(ClusterState currentState) { if (currentIndexMetadata == null) { // Index doesn't exist - create it and start recovery // Make sure that the index we are about to create has a valid name - ensureValidIndexName(currentState, snapshotIndexMetadata, renamedIndexName); - shardLimitValidator.validateShardLimit(snapshotIndexMetadata.getSettings(), currentState); + ensureValidIndexName(currentState.metadata(), currentState.routingTable(), snapshotIndexMetadata, renamedIndexName); + shardLimitValidator.validateShardLimit( + snapshotIndexMetadata.getSettings(), + currentState.nodes(), + currentState.metadata() + ); final IndexMetadata.Builder indexMdBuilder = restoreToCreateNewIndex( snapshotIndexMetadata, @@ -1789,9 +1793,14 @@ private static IndexMetadata.Builder restoreOverClosedIndex( return indexMdBuilder; } - private void ensureValidIndexName(ClusterState currentState, IndexMetadata snapshotIndexMetadata, String renamedIndexName) { + private void ensureValidIndexName( + Metadata metadata, + RoutingTable routingTable, + IndexMetadata snapshotIndexMetadata, + String renamedIndexName + ) { final boolean isHidden = snapshotIndexMetadata.isHidden(); - MetadataCreateIndexService.validateIndexName(renamedIndexName, currentState); + MetadataCreateIndexService.validateIndexName(renamedIndexName, metadata, routingTable); createIndexService.validateDotIndex(renamedIndexName, isHidden); createIndexService.validateIndexSettings(renamedIndexName, snapshotIndexMetadata.getSettings(), false); } diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexServiceTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexServiceTests.java index f7d343b43b29c..01394a7abbcd5 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexServiceTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexServiceTests.java @@ -170,18 +170,14 @@ public void testValidateShrinkIndex() { assertEquals( "index [source] already exists", - expectThrows( - ResourceAlreadyExistsException.class, - () -> MetadataCreateIndexService.validateShrinkIndex(state, "target", "source", Settings.EMPTY) - ).getMessage() + expectThrows(ResourceAlreadyExistsException.class, () -> validateShrinkIndex(state, "target", "source", Settings.EMPTY)) + .getMessage() ); assertEquals( "no such index [no_such_index]", - expectThrows( - IndexNotFoundException.class, - () -> MetadataCreateIndexService.validateShrinkIndex(state, "no_such_index", "target", Settings.EMPTY) - ).getMessage() + expectThrows(IndexNotFoundException.class, () -> validateShrinkIndex(state, "no_such_index", "target", Settings.EMPTY)) + .getMessage() ); Settings targetSettings = Settings.builder().put("index.number_of_shards", 1).build(); @@ -189,7 +185,7 @@ public void testValidateShrinkIndex() { "can't shrink an index with only one shard", expectThrows( IllegalArgumentException.class, - () -> MetadataCreateIndexService.validateShrinkIndex( + () -> validateShrinkIndex( createClusterState("source", 1, 0, Settings.builder().put("index.blocks.write", true).build()), "source", "target", @@ -202,7 +198,7 @@ public void testValidateShrinkIndex() { "the number of target shards [10] must be less that the number of source shards [5]", expectThrows( IllegalArgumentException.class, - () -> MetadataCreateIndexService.validateShrinkIndex( + () -> validateShrinkIndex( createClusterState("source", 5, 0, Settings.builder().put("index.blocks.write", true).build()), "source", "target", @@ -215,7 +211,7 @@ public void testValidateShrinkIndex() { "index source must be read-only to resize index. use \"index.blocks.write=true\"", expectThrows( IllegalStateException.class, - () -> MetadataCreateIndexService.validateShrinkIndex( + () -> validateShrinkIndex( createClusterState("source", randomIntBetween(2, 100), randomIntBetween(0, 10), Settings.EMPTY), "source", "target", @@ -228,7 +224,7 @@ public void testValidateShrinkIndex() { "index source must have all shards allocated on the same node to shrink index", expectThrows( IllegalStateException.class, - () -> MetadataCreateIndexService.validateShrinkIndex(state, "source", "target", targetSettings) + () -> validateShrinkIndex(state, "source", "target", targetSettings) ).getMessage() ); @@ -236,7 +232,7 @@ public void testValidateShrinkIndex() { "the number of source shards [8] must be a multiple of [3]", expectThrows( IllegalArgumentException.class, - () -> MetadataCreateIndexService.validateShrinkIndex( + () -> validateShrinkIndex( createClusterState("source", 8, randomIntBetween(0, 10), Settings.builder().put("index.blocks.write", true).build()), "source", "target", @@ -267,12 +263,7 @@ public void testValidateShrinkIndex() { do { targetShards = randomIntBetween(1, numShards / 2); } while (isShrinkable(numShards, targetShards) == false); - MetadataCreateIndexService.validateShrinkIndex( - clusterState, - "source", - "target", - Settings.builder().put("index.number_of_shards", targetShards).build() - ); + validateShrinkIndex(clusterState, "source", "target", Settings.builder().put("index.number_of_shards", targetShards).build()); } public void testValidateSplitIndex() { @@ -287,25 +278,21 @@ public void testValidateSplitIndex() { assertEquals( "index [source] already exists", - expectThrows( - ResourceAlreadyExistsException.class, - () -> MetadataCreateIndexService.validateSplitIndex(state, "target", "source", targetSettings) - ).getMessage() + expectThrows(ResourceAlreadyExistsException.class, () -> validateSplitIndex(state, "target", "source", targetSettings)) + .getMessage() ); assertEquals( "no such index [no_such_index]", - expectThrows( - IndexNotFoundException.class, - () -> MetadataCreateIndexService.validateSplitIndex(state, "no_such_index", "target", targetSettings) - ).getMessage() + expectThrows(IndexNotFoundException.class, () -> validateSplitIndex(state, "no_such_index", "target", targetSettings)) + .getMessage() ); assertEquals( "the number of source shards [10] must be less that the number of target shards [5]", expectThrows( IllegalArgumentException.class, - () -> MetadataCreateIndexService.validateSplitIndex( + () -> validateSplitIndex( createClusterState("source", 10, 0, Settings.builder().put("index.blocks.write", true).build()), "source", "target", @@ -318,7 +305,7 @@ public void testValidateSplitIndex() { "index source must be read-only to resize index. use \"index.blocks.write=true\"", expectThrows( IllegalStateException.class, - () -> MetadataCreateIndexService.validateSplitIndex( + () -> validateSplitIndex( createClusterState("source", randomIntBetween(2, 100), randomIntBetween(0, 10), Settings.EMPTY), "source", "target", @@ -331,7 +318,7 @@ public void testValidateSplitIndex() { "the number of source shards [3] must be a factor of [4]", expectThrows( IllegalArgumentException.class, - () -> MetadataCreateIndexService.validateSplitIndex( + () -> validateSplitIndex( createClusterState("source", 3, randomIntBetween(0, 10), Settings.builder().put("index.blocks.write", true).build()), "source", "target", @@ -367,12 +354,7 @@ public void testValidateSplitIndex() { routingTable = ESAllocationTestCase.startInitializingShardsAndReroute(service, clusterState, "source").routingTable(); clusterState = ClusterState.builder(clusterState).routingTable(routingTable).build(); - MetadataCreateIndexService.validateSplitIndex( - clusterState, - "source", - "target", - Settings.builder().put("index.number_of_shards", targetShards).build() - ); + validateSplitIndex(clusterState, "source", "target", Settings.builder().put("index.number_of_shards", targetShards).build()); } public void testPrepareResizeIndexSettings() { @@ -528,7 +510,9 @@ private void runPrepareResizeIndexSettingsTest( additionalIndexScopedSettings.stream() ).collect(Collectors.toSet()); MetadataCreateIndexService.prepareResizeIndexSettings( - clusterState, + clusterState.metadata(), + clusterState.blocks(), + clusterState.routingTable(), indexSettingsBuilder, clusterState.metadata().index(indexName).getIndex(), "target", @@ -576,9 +560,10 @@ public void testValidateIndexName() throws Exception { } private static void validateIndexName(MetadataCreateIndexService metadataCreateIndexService, String indexName, String errorMessage) { + ClusterState state = ClusterState.builder(ClusterName.DEFAULT).build(); InvalidIndexNameException e = expectThrows( InvalidIndexNameException.class, - () -> MetadataCreateIndexService.validateIndexName(indexName, ClusterState.builder(ClusterName.DEFAULT).build()) + () -> MetadataCreateIndexService.validateIndexName(indexName, state.metadata(), state.routingTable()) ); assertThat(e.getMessage(), endsWith(errorMessage)); } @@ -1423,4 +1408,19 @@ private void withTemporaryClusterService(BiConsumer threadPool.shutdown(); } } + + private List validateShrinkIndex(ClusterState state, String sourceIndex, String targetIndexName, Settings targetIndexSettings) { + return MetadataCreateIndexService.validateShrinkIndex( + state.metadata(), + state.blocks(), + state.routingTable(), + sourceIndex, + targetIndexName, + targetIndexSettings + ); + } + + private void validateSplitIndex(ClusterState state, String sourceIndex, String targetIndexName, Settings targetIndexSettings) { + MetadataCreateIndexService.validateSplitIndex(state.metadata(), state.blocks(), sourceIndex, targetIndexName, targetIndexSettings); + } } diff --git a/server/src/test/java/org/elasticsearch/health/node/ShardsCapacityHealthIndicatorServiceTests.java b/server/src/test/java/org/elasticsearch/health/node/ShardsCapacityHealthIndicatorServiceTests.java index 1c3d0d486b282..a5a61eab4df9e 100644 --- a/server/src/test/java/org/elasticsearch/health/node/ShardsCapacityHealthIndicatorServiceTests.java +++ b/server/src/test/java/org/elasticsearch/health/node/ShardsCapacityHealthIndicatorServiceTests.java @@ -341,8 +341,10 @@ public void testCalculateMethods() { maxConfiguredShardsPerNode, numberOfNewShards, replicas, - state) -> { - assertEquals(mockedState, state); + discoveryNodes, + metadata) -> { + assertEquals(mockedState.nodes(), discoveryNodes); + assertEquals(mockedState.metadata(), metadata); assertEquals(randomMaxShardsPerNodeSetting, maxConfiguredShardsPerNode); return new ShardLimitValidator.Result( numberOfNewShards != shardsToAdd && replicas == 1, @@ -353,13 +355,19 @@ public void testCalculateMethods() { ); }; - assertEquals(calculateFrom(randomMaxShardsPerNodeSetting, mockedState, checkerWrapper.apply(5)).status(), RED); - assertEquals(calculateFrom(randomMaxShardsPerNodeSetting, mockedState, checkerWrapper.apply(10)).status(), YELLOW); + assertEquals( + calculateFrom(randomMaxShardsPerNodeSetting, mockedState.nodes(), mockedState.metadata(), checkerWrapper.apply(5)).status(), + RED + ); + assertEquals( + calculateFrom(randomMaxShardsPerNodeSetting, mockedState.nodes(), mockedState.metadata(), checkerWrapper.apply(10)).status(), + YELLOW + ); // Let's cover the holes :) Stream.of(randomIntBetween(1, 4), randomIntBetween(6, 9), randomIntBetween(11, Integer.MAX_VALUE)) .map(checkerWrapper) - .map(checker -> calculateFrom(randomMaxShardsPerNodeSetting, mockedState, checker)) + .map(checker -> calculateFrom(randomMaxShardsPerNodeSetting, mockedState.nodes(), mockedState.metadata(), checker)) .map(ShardsCapacityHealthIndicatorService.StatusResult::status) .forEach(status -> assertEquals(status, GREEN)); } diff --git a/server/src/test/java/org/elasticsearch/indices/ShardLimitValidatorTests.java b/server/src/test/java/org/elasticsearch/indices/ShardLimitValidatorTests.java index 0eea536ddbff1..36b0711ad6c13 100644 --- a/server/src/test/java/org/elasticsearch/indices/ShardLimitValidatorTests.java +++ b/server/src/test/java/org/elasticsearch/indices/ShardLimitValidatorTests.java @@ -41,7 +41,13 @@ public class ShardLimitValidatorTests extends ESTestCase { @FunctionalInterface interface CheckShardLimitMethod { - ShardLimitValidator.Result call(int maxConfiguredShardsPerNode, int numberOfNewShards, int replicas, ClusterState state); + ShardLimitValidator.Result call( + int maxConfiguredShardsPerNode, + int numberOfNewShards, + int replicas, + DiscoveryNodes discoveryNodes, + Metadata metadata + ); } public void testOverShardLimit() { @@ -63,7 +69,8 @@ private void testOverShardLimit(CheckShardLimitMethod targetMethod, String group counts.getShardsPerNode(), counts.getFailingIndexShards(), counts.getFailingIndexReplicas(), - state + state.nodes(), + state.metadata() ); int totalShards = counts.getFailingIndexShards() * (1 + counts.getFailingIndexReplicas()); @@ -113,7 +120,13 @@ private void testUnderShardLimit(CheckShardLimitMethod targetMethod, String grou int existingShards = counts.getFirstIndexShards() * (1 + counts.getFirstIndexReplicas()); int availableRoom = maxShardsInCluster - existingShards; int shardsToAdd = randomIntBetween(1, Math.max(availableRoom / (replicas + 1), 1)); - ShardLimitValidator.Result shardLimitsResult = targetMethod.call(counts.getShardsPerNode(), shardsToAdd, replicas, state); + ShardLimitValidator.Result shardLimitsResult = targetMethod.call( + counts.getShardsPerNode(), + shardsToAdd, + replicas, + state.nodes(), + state.metadata() + ); assertTrue(shardLimitsResult.canAddShards()); assertEquals(shardLimitsResult.maxShardsInCluster(), counts.getShardsPerNode() * nodesInCluster); assertEquals(shardLimitsResult.totalShardsToAdd(), shardsToAdd * (replicas + 1)); @@ -142,7 +155,7 @@ public void testValidateShardLimitOpenIndices() { ShardLimitValidator shardLimitValidator = createTestShardLimitService(counts.getShardsPerNode(), group); ValidationException exception = expectThrows( ValidationException.class, - () -> shardLimitValidator.validateShardLimit(state, indices) + () -> shardLimitValidator.validateShardLimit(state.nodes(), state.metadata(), indices) ); assertEquals( "Validation Failed: 1: this action would add [" @@ -168,11 +181,11 @@ public void testValidateShardLimitUpdateReplicas() { final Index[] indices = getIndices(state); final ShardLimitValidator shardLimitValidator = createTestShardLimitService(shardsPerNode, group); - shardLimitValidator.validateShardLimitOnReplicaUpdate(state, indices, nodesInCluster - 1); + shardLimitValidator.validateShardLimitOnReplicaUpdate(state.nodes(), state.metadata(), indices, nodesInCluster - 1); ValidationException exception = expectThrows( ValidationException.class, - () -> shardLimitValidator.validateShardLimitOnReplicaUpdate(state, indices, nodesInCluster) + () -> shardLimitValidator.validateShardLimitOnReplicaUpdate(state.nodes(), state.metadata(), indices, nodesInCluster) ); assertEquals( "Validation Failed: 1: this action would add [" diff --git a/x-pack/plugin/downsample/src/main/java/org/elasticsearch/xpack/downsample/TransportDownsampleAction.java b/x-pack/plugin/downsample/src/main/java/org/elasticsearch/xpack/downsample/TransportDownsampleAction.java index d8c9acff156ce..58a0370efb50e 100644 --- a/x-pack/plugin/downsample/src/main/java/org/elasticsearch/xpack/downsample/TransportDownsampleAction.java +++ b/x-pack/plugin/downsample/src/main/java/org/elasticsearch/xpack/downsample/TransportDownsampleAction.java @@ -267,7 +267,7 @@ protected void masterOperation( return; } try { - MetadataCreateIndexService.validateIndexName(downsampleIndexName, state); + MetadataCreateIndexService.validateIndexName(downsampleIndexName, state.metadata(), state.routingTable()); } catch (ResourceAlreadyExistsException e) { // ignore index already exists }