Skip to content

Commit 5c5d723

Browse files
authored
Improve error message when aliases are not supported (#25728)
With #23997 and #25268 we have changed put alias, delete alias, update aliases and delete index to not accept aliases. Instead concrete indices should be provided as their index parameter. This commit improves the error message in case aliases are provided, from an IndexNotFoundException (404 status code) with "no such index" message, to an IllegalArgumentException (400 status code) with "The provided expression [alias] matches an alias, specify the corresponding concrete indices instead." message. Note that there is no specific error message for the case where wildcard expressions match one or more aliases. In fact, aliases are simply ignored when expanding wildcards for such APIs. An error is thrown only when the expression ends up matching no indices at all, and allow_no_indices is set to false. In that case the error is still the generic "404 - no such index".
1 parent ff4a251 commit 5c5d723

File tree

5 files changed

+181
-86
lines changed

5 files changed

+181
-86
lines changed

core/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -175,14 +175,20 @@ Index[] concreteIndices(Context context, String... indexExpressions) {
175175
final Set<Index> concreteIndices = new HashSet<>(expressions.size());
176176
for (String expression : expressions) {
177177
AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(expression);
178-
if (aliasOrIndex == null || (aliasOrIndex.isAlias() && context.getOptions().ignoreAliases())) {
178+
if (aliasOrIndex == null ) {
179179
if (failNoIndices) {
180180
IndexNotFoundException infe = new IndexNotFoundException(expression);
181181
infe.setResources("index_expression", expression);
182182
throw infe;
183183
} else {
184184
continue;
185185
}
186+
} else if (aliasOrIndex.isAlias() && context.getOptions().ignoreAliases()) {
187+
if (failNoIndices) {
188+
throw aliasesNotSupportedException(expression);
189+
} else {
190+
continue;
191+
}
186192
}
187193

188194
Collection<IndexMetaData> resolvedIndices = aliasOrIndex.getIndices();
@@ -192,7 +198,8 @@ Index[] concreteIndices(Context context, String... indexExpressions) {
192198
for (IndexMetaData indexMetaData : resolvedIndices) {
193199
indexNames[i++] = indexMetaData.getIndex().getName();
194200
}
195-
throw new IllegalArgumentException("Alias [" + expression + "] has more than one indices associated with it [" + Arrays.toString(indexNames) + "], can't execute a single index op");
201+
throw new IllegalArgumentException("Alias [" + expression + "] has more than one indices associated with it [" +
202+
Arrays.toString(indexNames) + "], can't execute a single index op");
196203
}
197204

198205
for (IndexMetaData index : resolvedIndices) {
@@ -220,6 +227,11 @@ Index[] concreteIndices(Context context, String... indexExpressions) {
220227
return concreteIndices.toArray(new Index[concreteIndices.size()]);
221228
}
222229

230+
private static IllegalArgumentException aliasesNotSupportedException(String expression) {
231+
return new IllegalArgumentException("The provided expression [" + expression + "] matches an " +
232+
"alias, specify the corresponding concrete indices instead.");
233+
}
234+
223235
/**
224236
* Utility method that allows to resolve an index expression to its corresponding single concrete index.
225237
* Callers should make sure they provide proper {@link org.elasticsearch.action.support.IndicesOptions}
@@ -270,8 +282,7 @@ public String[] filteringAliases(ClusterState state, String index, String... exp
270282
}
271283

272284
/**
273-
* Iterates through the list of indices and selects the effective list of required aliases for the
274-
* given index.
285+
* Iterates through the list of indices and selects the effective list of required aliases for the given index.
275286
* <p>Only aliases where the given predicate tests successfully are returned. If the indices list contains a non-required reference to
276287
* the index itself - null is returned. Returns <tt>null</tt> if no filtering is required.
277288
*/
@@ -588,7 +599,7 @@ private Set<String> innerResolve(Context context, List<String> expressions, Indi
588599
for (int i = 0; i < expressions.size(); i++) {
589600
String expression = expressions.get(i);
590601
if (Strings.isEmpty(expression)) {
591-
throw infe(expression);
602+
throw indexNotFoundException(expression);
592603
}
593604
if (aliasOrIndexExists(options, metaData, expression)) {
594605
if (result != null) {
@@ -608,8 +619,14 @@ private Set<String> innerResolve(Context context, List<String> expressions, Indi
608619
result = new HashSet<>(expressions.subList(0, i));
609620
}
610621
if (!Regex.isSimpleMatchPattern(expression)) {
611-
if (!unavailableIgnoredOrExists(options, metaData, expression)) {
612-
throw infe(expression);
622+
//TODO why does wildcard resolver throw exceptions regarding non wildcarded expressions? This should not be done here.
623+
if (options.ignoreUnavailable() == false) {
624+
AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(expression);
625+
if (aliasOrIndex == null) {
626+
throw indexNotFoundException(expression);
627+
} else if (aliasOrIndex.isAlias() && options.ignoreAliases()) {
628+
throw aliasesNotSupportedException(expression);
629+
}
613630
}
614631
if (add) {
615632
result.add(expression);
@@ -628,7 +645,7 @@ private Set<String> innerResolve(Context context, List<String> expressions, Indi
628645
result.removeAll(expand);
629646
}
630647
if (options.allowNoIndices() == false && matches.isEmpty()) {
631-
throw infe(expression);
648+
throw indexNotFoundException(expression);
632649
}
633650
if (Regex.isSimpleMatchPattern(expression)) {
634651
wildcardSeen = true;
@@ -637,17 +654,13 @@ private Set<String> innerResolve(Context context, List<String> expressions, Indi
637654
return result;
638655
}
639656

640-
private static boolean unavailableIgnoredOrExists(IndicesOptions options, MetaData metaData, String expression) {
641-
return options.ignoreUnavailable() || aliasOrIndexExists(options, metaData, expression);
642-
}
643-
644657
private static boolean aliasOrIndexExists(IndicesOptions options, MetaData metaData, String expression) {
645658
AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(expression);
646659
//treat aliases as unavailable indices when ignoreAliases is set to true (e.g. delete index and update aliases api)
647660
return aliasOrIndex != null && (options.ignoreAliases() == false || aliasOrIndex.isAlias() == false);
648661
}
649662

650-
private static IndexNotFoundException infe(String expression) {
663+
private static IndexNotFoundException indexNotFoundException(String expression) {
651664
IndexNotFoundException infe = new IndexNotFoundException(expression);
652665
infe.setResources("index_or_alias", expression);
653666
return infe;

core/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,9 @@
3333
import org.elasticsearch.cluster.metadata.AliasOrIndex;
3434
import org.elasticsearch.cluster.metadata.IndexMetaData;
3535
import org.elasticsearch.common.StopWatch;
36-
import org.elasticsearch.common.Strings;
3736
import org.elasticsearch.common.settings.Settings;
3837
import org.elasticsearch.common.unit.TimeValue;
3938
import org.elasticsearch.common.xcontent.XContentType;
40-
import org.elasticsearch.index.IndexNotFoundException;
4139
import org.elasticsearch.index.query.QueryBuilder;
4240
import org.elasticsearch.index.query.QueryBuilders;
4341
import org.elasticsearch.rest.action.admin.indices.AliasesNotFoundException;
@@ -442,8 +440,10 @@ public void testDeleteAliases() throws Exception {
442440
assertTrue(admin().indices().prepareAliasesExist("foo").get().exists());
443441
assertFalse(admin().indices().prepareAliasesExist("foo").setIndices("foo_foo").get().exists());
444442
assertTrue(admin().indices().prepareAliasesExist("foo").setIndices("bar_bar").get().exists());
445-
expectThrows(IndexNotFoundException.class, () -> admin().indices().prepareAliases()
443+
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> admin().indices().prepareAliases()
446444
.addAliasAction(AliasActions.remove().index("foo").alias("foo")).execute().actionGet());
445+
assertEquals("The provided expression [foo] matches an alias, specify the corresponding concrete indices instead.",
446+
iae.getMessage());
447447
}
448448

449449
public void testWaitForAliasCreationMultipleShards() throws Exception {
@@ -824,10 +824,10 @@ public void testAliasesCanBeAddedToIndicesOnly() throws Exception {
824824
logger.info("--> adding [week_20] alias to [2017-05-20]");
825825
assertAcked(admin().indices().prepareAliases().addAlias("2017-05-20", "week_20"));
826826

827-
IndexNotFoundException infe = expectThrows(IndexNotFoundException.class, () -> admin().indices().prepareAliases()
827+
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> admin().indices().prepareAliases()
828828
.addAliasAction(AliasActions.add().index("week_20").alias("tmp")).execute().actionGet());
829-
assertEquals("week_20", infe.getIndex().getName());
830-
829+
assertEquals("The provided expression [week_20] matches an alias, specify the corresponding concrete indices instead.",
830+
iae.getMessage());
831831
assertAcked(admin().indices().prepareAliases().addAliasAction(AliasActions.add().index("2017-05-20").alias("tmp")).execute().get());
832832
}
833833

@@ -916,8 +916,10 @@ public void testAliasActionRemoveIndex() throws InterruptedException, ExecutionE
916916
assertAcked(admin().indices().prepareAliases().addAlias("foo_foo", "foo"));
917917
assertAcked(admin().indices().prepareAliases().addAlias("bar_bar", "foo"));
918918

919-
expectThrows(IndexNotFoundException.class,
919+
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class,
920920
() -> client().admin().indices().prepareAliases().removeIndex("foo").execute().actionGet());
921+
assertEquals("The provided expression [foo] matches an alias, specify the corresponding concrete indices instead.",
922+
iae.getMessage());
921923

922924
assertAcked(client().admin().indices().prepareAliases().removeIndex("foo*").execute().get());
923925
assertFalse(client().admin().indices().prepareExists("foo_foo").execute().actionGet().isExists());

core/src/test/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolverTests.java

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -657,9 +657,10 @@ public void testConcreteIndicesWildcardAndAliases() {
657657
assertEquals(1, indexNamesIndexWildcard.length);
658658
assertEquals("foo_foo", indexNamesIndexWildcard[0]);
659659

660-
IndexNotFoundException infe = expectThrows(IndexNotFoundException.class,
660+
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class,
661661
() -> indexNameExpressionResolver.concreteIndexNames(state, ignoreAliasesOptions, "foo"));
662-
assertThat(infe.getIndex().getName(), equalTo("foo"));
662+
assertEquals("The provided expression [foo] matches an alias, specify the corresponding concrete indices instead.",
663+
iae.getMessage());
663664

664665
// when ignoreAliases option is not set, concreteIndexNames resolves the provided
665666
// expressions against the defined indices and aliases
@@ -1005,11 +1006,13 @@ public void testDeleteIndexIgnoresAliases() {
10051006
IndexNotFoundException infe = expectThrows(IndexNotFoundException.class,
10061007
() -> indexNameExpressionResolver.concreteIndexNames(state, new DeleteIndexRequest("does_not_exist")));
10071008
assertEquals("does_not_exist", infe.getIndex().getName());
1009+
assertEquals("no such index", infe.getMessage());
10081010
}
10091011
{
1010-
IndexNotFoundException infe = expectThrows(IndexNotFoundException.class,
1012+
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class,
10111013
() -> indexNameExpressionResolver.concreteIndexNames(state, new DeleteIndexRequest("test-alias")));
1012-
assertEquals("test-alias", infe.getIndex().getName());
1014+
assertEquals("The provided expression [test-alias] matches an alias, " +
1015+
"specify the corresponding concrete indices instead.", iae.getMessage());
10131016
}
10141017
{
10151018
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("test-alias");
@@ -1049,11 +1052,16 @@ public void testIndicesAliasesRequestIgnoresAliases() {
10491052
ClusterState state = ClusterState.builder(new ClusterName("_name")).metaData(mdBuilder).build();
10501053
{
10511054
IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.add().index("test-alias");
1052-
expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions));
1055+
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class,
1056+
() -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions));
1057+
assertEquals("The provided expression [test-alias] matches an alias, " +
1058+
"specify the corresponding concrete indices instead.", iae.getMessage());
10531059
}
10541060
{
10551061
IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.add().index("test-a*");
1056-
expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions));
1062+
IndexNotFoundException infe = expectThrows(IndexNotFoundException.class,
1063+
() -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions));
1064+
assertEquals("test-a*", infe.getIndex().getName());
10571065
}
10581066
{
10591067
IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.add().index("test-index");
@@ -1069,11 +1077,16 @@ public void testIndicesAliasesRequestIgnoresAliases() {
10691077
}
10701078
{
10711079
IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.remove().index("test-alias");
1072-
expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions));
1080+
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class,
1081+
() -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions));
1082+
assertEquals("The provided expression [test-alias] matches an alias, " +
1083+
"specify the corresponding concrete indices instead.", iae.getMessage());
10731084
}
10741085
{
10751086
IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.remove().index("test-a*");
1076-
expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions));
1087+
IndexNotFoundException infe = expectThrows(IndexNotFoundException.class,
1088+
() -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions));
1089+
assertEquals("test-a*", infe.getIndex().getName());
10771090
}
10781091
{
10791092
IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.remove().index("test-index");
@@ -1089,11 +1102,16 @@ public void testIndicesAliasesRequestIgnoresAliases() {
10891102
}
10901103
{
10911104
IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.removeIndex().index("test-alias");
1092-
expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions));
1105+
IllegalArgumentException iae = expectThrows(IllegalArgumentException.class,
1106+
() -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions));
1107+
assertEquals("The provided expression [test-alias] matches an alias, " +
1108+
"specify the corresponding concrete indices instead.", iae.getMessage());
10931109
}
10941110
{
10951111
IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.removeIndex().index("test-a*");
1096-
expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions));
1112+
IndexNotFoundException infe = expectThrows(IndexNotFoundException.class,
1113+
() -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions));
1114+
assertEquals("test-a*", infe.getIndex().getName());
10971115
}
10981116
{
10991117
IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.removeIndex().index("test-index");

0 commit comments

Comments
 (0)