Skip to content

Commit 1ea0420

Browse files
committed
Check dot-index rules after template application (elastic#52087)
Previously, the dot-index rules (namely, that indices with dot-prefixed names should be either hidden indices or system indices) was done before* template application, and so only checked for the `index.hidden` setting in the request, ignoring if that setting was set via a template. This commit moves that check to a different method, which is applied after templates have been resolved and applied to the index settings.
1 parent 5a72b23 commit 1ea0420

File tree

4 files changed

+44
-28
lines changed

4 files changed

+44
-28
lines changed

server/src/main/java/org/elasticsearch/action/admin/indices/rollover/TransportRolloverAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ protected void masterOperation(Task task, final RolloverRequest rolloverRequest,
132132
final String rolloverIndexName = indexNameExpressionResolver.resolveDateMathExpression(unresolvedName);
133133
final Boolean isHidden = IndexMetaData.INDEX_HIDDEN_SETTING.exists(rolloverRequest.getCreateIndexRequest().settings()) ?
134134
IndexMetaData.INDEX_HIDDEN_SETTING.get(rolloverRequest.getCreateIndexRequest().settings()) : null;
135-
createIndexService.validateIndexName(rolloverIndexName, state, isHidden); // fails if the index already exists
135+
createIndexService.validateIndexName(rolloverIndexName, state); // fails if the index already exists
136136
checkNoDuplicatedAliasInIndexTemplate(metaData, rolloverIndexName, rolloverRequest.getAlias(), isHidden);
137137
IndicesStatsRequest statsRequest = new IndicesStatsRequest().indices(rolloverRequest.getAlias())
138138
.clear()

server/src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,32 @@ public MetaDataCreateIndexService(
169169
/**
170170
* Validate the name for an index against some static rules and a cluster state.
171171
*/
172-
public void validateIndexName(String index, ClusterState state, @Nullable Boolean isHidden) {
172+
public void validateIndexName(String index, ClusterState state) {
173173
validateIndexOrAliasName(index, InvalidIndexNameException::new);
174174
if (!index.toLowerCase(Locale.ROOT).equals(index)) {
175175
throw new InvalidIndexNameException(index, "must be lowercase");
176176
}
177177

178+
// NOTE: dot-prefixed index names are validated after template application, not here
179+
180+
if (state.routingTable().hasIndex(index)) {
181+
throw new ResourceAlreadyExistsException(state.routingTable().index(index).getIndex());
182+
}
183+
if (state.metaData().hasIndex(index)) {
184+
throw new ResourceAlreadyExistsException(state.metaData().index(index).getIndex());
185+
}
186+
if (state.metaData().hasAlias(index)) {
187+
throw new InvalidIndexNameException(index, "already exists as alias");
188+
}
189+
}
190+
191+
/**
192+
* Validates (if this index has a dot-prefixed name) whether it follows the rules for dot-prefixed indices.
193+
* @param index The name of the index in question
194+
* @param state The current cluster state
195+
* @param isHidden Whether or not this is a hidden index
196+
*/
197+
public void validateDotIndex(String index, ClusterState state, @Nullable Boolean isHidden) {
178198
if (index.charAt(0) == '.') {
179199
List<SystemIndexDescriptor> matchingDescriptors = systemIndexDescriptors.stream()
180200
.filter(descriptor -> descriptor.matchesIndexPattern(index))
@@ -200,15 +220,6 @@ public void validateIndexName(String index, ClusterState state, @Nullable Boolea
200220
throw new IllegalStateException(errorMessage.toString());
201221
}
202222
}
203-
if (state.routingTable().hasIndex(index)) {
204-
throw new ResourceAlreadyExistsException(state.routingTable().index(index).getIndex());
205-
}
206-
if (state.metaData().hasIndex(index)) {
207-
throw new ResourceAlreadyExistsException(state.metaData().index(index).getIndex());
208-
}
209-
if (state.metaData().hasAlias(index)) {
210-
throw new InvalidIndexNameException(index, "already exists as alias");
211-
}
212223
}
213224

214225
/**
@@ -322,10 +333,12 @@ public ClusterState applyCreateIndexRequest(ClusterState currentState, CreateInd
322333

323334
// we only find a template when its an API call (a new index)
324335
// find templates, highest order are better matching
325-
final Boolean isHidden = IndexMetaData.INDEX_HIDDEN_SETTING.exists(request.settings()) ?
336+
final Boolean isHiddenFromRequest = IndexMetaData.INDEX_HIDDEN_SETTING.exists(request.settings()) ?
326337
IndexMetaData.INDEX_HIDDEN_SETTING.get(request.settings()) : null;
327338
final List<IndexTemplateMetaData> templates = sourceMetaData == null ?
328-
Collections.unmodifiableList(MetaDataIndexTemplateService.findTemplates(currentState.metaData(), request.index(), isHidden)) :
339+
Collections.unmodifiableList(MetaDataIndexTemplateService.findTemplates(currentState.metaData(),
340+
request.index(),
341+
isHiddenFromRequest)) :
329342
Collections.emptyList();
330343

331344
final Map<String, Map<String, Object>> mappings = Collections.unmodifiableMap(parseMappings(request.mappings(), templates,
@@ -335,6 +348,9 @@ public ClusterState applyCreateIndexRequest(ClusterState currentState, CreateInd
335348
aggregateIndexSettings(currentState, request, templates, mappings, sourceMetaData, settings, indexScopedSettings);
336349
int routingNumShards = getIndexNumberOfRoutingShards(aggregatedIndexSettings, sourceMetaData);
337350

351+
final boolean isHiddenAfterTemplates = IndexMetaData.INDEX_HIDDEN_SETTING.get(aggregatedIndexSettings);
352+
validateDotIndex(request.index(), currentState, isHiddenAfterTemplates);
353+
338354
// remove the setting it's temporary and is only relevant once we create the index
339355
final Settings.Builder settingsBuilder = Settings.builder().put(aggregatedIndexSettings);
340356
settingsBuilder.remove(IndexMetaData.INDEX_NUMBER_OF_ROUTING_SHARDS_SETTING.getKey());
@@ -742,8 +758,7 @@ private static IndexService validateActiveShardCountAndCreateIndexService(String
742758
}
743759

744760
private void validate(CreateIndexClusterStateUpdateRequest request, ClusterState state) {
745-
boolean isHidden = IndexMetaData.INDEX_HIDDEN_SETTING.get(request.settings());
746-
validateIndexName(request.index(), state, isHidden);
761+
validateIndexName(request.index(), state);
747762
validateIndexSettings(request.index(), request.settings(), forbidPrivateIndexSettings);
748763
}
749764

server/src/main/java/org/elasticsearch/snapshots/RestoreService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,8 @@ public ClusterState execute(ClusterState currentState) {
279279
// Index doesn't exist - create it and start recovery
280280
// Make sure that the index we are about to create has a validate name
281281
boolean isHidden = IndexMetaData.INDEX_HIDDEN_SETTING.get(snapshotIndexMetaData.getSettings());
282-
createIndexService.validateIndexName(renamedIndexName, currentState, isHidden);
282+
createIndexService.validateIndexName(renamedIndexName, currentState);
283+
createIndexService.validateDotIndex(renamedIndexName, currentState, isHidden);
283284
createIndexService.validateIndexSettings(renamedIndexName, snapshotIndexMetaData.getSettings(), false);
284285
IndexMetaData.Builder indexMdBuilder = IndexMetaData.builder(snapshotIndexMetaData)
285286
.state(IndexMetaData.State.OPEN)

server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexServiceTests.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ public void testValidateIndexName() throws Exception {
517517
private void validateIndexName(MetaDataCreateIndexService metaDataCreateIndexService, String indexName, String errorMessage) {
518518
InvalidIndexNameException e = expectThrows(InvalidIndexNameException.class,
519519
() -> metaDataCreateIndexService.validateIndexName(indexName, ClusterState.builder(ClusterName.CLUSTER_NAME_SETTING
520-
.getDefault(Settings.EMPTY)).build(), false));
520+
.getDefault(Settings.EMPTY)).build()));
521521
assertThat(e.getMessage(), endsWith(errorMessage));
522522
}
523523

@@ -586,7 +586,7 @@ public void testShardLimit() {
586586
assertThat(e, hasToString(containsString(expectedMessage)));
587587
}
588588

589-
public void testValidateIndexNameChecksSystemIndexNames() {
589+
public void testValidateDotIndex() {
590590
List<SystemIndexDescriptor> systemIndexDescriptors = new ArrayList<>();
591591
systemIndexDescriptors.add(new SystemIndexDescriptor(".test", "test"));
592592
systemIndexDescriptors.add(new SystemIndexDescriptor(".test3", "test"));
@@ -609,25 +609,25 @@ public void testValidateIndexNameChecksSystemIndexNames() {
609609
false
610610
);
611611
// Check deprecations
612-
checkerService.validateIndexName(".test2", ClusterState.EMPTY_STATE, false);
612+
checkerService.validateDotIndex(".test2", ClusterState.EMPTY_STATE, false);
613613
assertWarnings("index name [.test2] starts with a dot '.', in the next major version, index " +
614614
"names starting with a dot are reserved for hidden indices and system indices");
615615

616616
// Check non-system hidden indices don't trigger a warning
617-
checkerService.validateIndexName(".test2", ClusterState.EMPTY_STATE, true);
617+
checkerService.validateDotIndex(".test2", ClusterState.EMPTY_STATE, true);
618618

619619
// Check NO deprecation warnings if we give the index name
620-
checkerService.validateIndexName(".test", ClusterState.EMPTY_STATE, false);
621-
checkerService.validateIndexName(".test3", ClusterState.EMPTY_STATE, false);
620+
checkerService.validateDotIndex(".test", ClusterState.EMPTY_STATE, false);
621+
checkerService.validateDotIndex(".test3", ClusterState.EMPTY_STATE, false);
622622

623623
// Check that patterns with wildcards work
624-
checkerService.validateIndexName(".pattern-test", ClusterState.EMPTY_STATE, false);
625-
checkerService.validateIndexName(".pattern-test-with-suffix", ClusterState.EMPTY_STATE, false);
626-
checkerService.validateIndexName(".pattern-test-other-suffix", ClusterState.EMPTY_STATE, false);
624+
checkerService.validateDotIndex(".pattern-test", ClusterState.EMPTY_STATE, false);
625+
checkerService.validateDotIndex(".pattern-test-with-suffix", ClusterState.EMPTY_STATE, false);
626+
checkerService.validateDotIndex(".pattern-test-other-suffix", ClusterState.EMPTY_STATE, false);
627627

628628
// Check that an exception is thrown if more than one descriptor matches the index name
629629
AssertionError exception = expectThrows(AssertionError.class,
630-
() -> checkerService.validateIndexName(".pattern-test-overlapping", ClusterState.EMPTY_STATE, false));
630+
() -> checkerService.validateDotIndex(".pattern-test-overlapping", ClusterState.EMPTY_STATE, false));
631631
assertThat(exception.getMessage(),
632632
containsString("index name [.pattern-test-overlapping] is claimed as a system index by multiple system index patterns:"));
633633
assertThat(exception.getMessage(), containsString("pattern: [.pattern-test*], description: [test-1]"));
@@ -667,11 +667,11 @@ public void testIndexNameExclusionsList() {
667667
);
668668

669669
excludedNames.forEach(name -> {
670-
checkerService.validateIndexName(name, ClusterState.EMPTY_STATE, false);
670+
checkerService.validateDotIndex(name, ClusterState.EMPTY_STATE, false);
671671
});
672672

673673
excludedNames.forEach(name -> {
674-
expectThrows(AssertionError.class, () -> checkerService.validateIndexName(name, ClusterState.EMPTY_STATE, true));
674+
expectThrows(AssertionError.class, () -> checkerService.validateDotIndex(name, ClusterState.EMPTY_STATE, true));
675675
});
676676
} finally {
677677
testThreadPool.shutdown();

0 commit comments

Comments
 (0)