From d5890520a3b9cd90035385aae2ed584545990d1b Mon Sep 17 00:00:00 2001 From: javanna Date: Fri, 14 Jul 2017 16:28:11 +0200 Subject: [PATCH] Improve error message when aliases are not supported 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". --- .../metadata/IndexNameExpressionResolver.java | 39 ++-- .../elasticsearch/aliases/IndexAliasesIT.java | 16 +- .../IndexNameExpressionResolverTests.java | 38 ++-- .../WildcardExpressionResolverTests.java | 170 ++++++++++++------ .../test/indices.delete/10_basic.yml | 4 +- 5 files changed, 181 insertions(+), 86 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java b/core/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java index 5f9bf5e370af3..17b43efdf9d85 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolver.java @@ -175,7 +175,7 @@ Index[] concreteIndices(Context context, String... indexExpressions) { final Set concreteIndices = new HashSet<>(expressions.size()); for (String expression : expressions) { AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(expression); - if (aliasOrIndex == null || (aliasOrIndex.isAlias() && context.getOptions().ignoreAliases())) { + if (aliasOrIndex == null ) { if (failNoIndices) { IndexNotFoundException infe = new IndexNotFoundException(expression); infe.setResources("index_expression", expression); @@ -183,6 +183,12 @@ Index[] concreteIndices(Context context, String... indexExpressions) { } else { continue; } + } else if (aliasOrIndex.isAlias() && context.getOptions().ignoreAliases()) { + if (failNoIndices) { + throw aliasesNotSupportedException(expression); + } else { + continue; + } } Collection resolvedIndices = aliasOrIndex.getIndices(); @@ -192,7 +198,8 @@ Index[] concreteIndices(Context context, String... indexExpressions) { for (IndexMetaData indexMetaData : resolvedIndices) { indexNames[i++] = indexMetaData.getIndex().getName(); } - throw new IllegalArgumentException("Alias [" + expression + "] has more than one indices associated with it [" + Arrays.toString(indexNames) + "], can't execute a single index op"); + throw new IllegalArgumentException("Alias [" + expression + "] has more than one indices associated with it [" + + Arrays.toString(indexNames) + "], can't execute a single index op"); } for (IndexMetaData index : resolvedIndices) { @@ -220,6 +227,11 @@ Index[] concreteIndices(Context context, String... indexExpressions) { return concreteIndices.toArray(new Index[concreteIndices.size()]); } + private static IllegalArgumentException aliasesNotSupportedException(String expression) { + return new IllegalArgumentException("The provided expression [" + expression + "] matches an " + + "alias, specify the corresponding concrete indices instead."); + } + /** * Utility method that allows to resolve an index expression to its corresponding single concrete index. * 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 } /** - * Iterates through the list of indices and selects the effective list of required aliases for the - * given index. + * Iterates through the list of indices and selects the effective list of required aliases for the given index. *

Only aliases where the given predicate tests successfully are returned. If the indices list contains a non-required reference to * the index itself - null is returned. Returns null if no filtering is required. */ @@ -588,7 +599,7 @@ private Set innerResolve(Context context, List expressions, Indi for (int i = 0; i < expressions.size(); i++) { String expression = expressions.get(i); if (Strings.isEmpty(expression)) { - throw infe(expression); + throw indexNotFoundException(expression); } if (aliasOrIndexExists(options, metaData, expression)) { if (result != null) { @@ -608,8 +619,14 @@ private Set innerResolve(Context context, List expressions, Indi result = new HashSet<>(expressions.subList(0, i)); } if (!Regex.isSimpleMatchPattern(expression)) { - if (!unavailableIgnoredOrExists(options, metaData, expression)) { - throw infe(expression); + //TODO why does wildcard resolver throw exceptions regarding non wildcarded expressions? This should not be done here. + if (options.ignoreUnavailable() == false) { + AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(expression); + if (aliasOrIndex == null) { + throw indexNotFoundException(expression); + } else if (aliasOrIndex.isAlias() && options.ignoreAliases()) { + throw aliasesNotSupportedException(expression); + } } if (add) { result.add(expression); @@ -628,7 +645,7 @@ private Set innerResolve(Context context, List expressions, Indi result.removeAll(expand); } if (options.allowNoIndices() == false && matches.isEmpty()) { - throw infe(expression); + throw indexNotFoundException(expression); } if (Regex.isSimpleMatchPattern(expression)) { wildcardSeen = true; @@ -637,17 +654,13 @@ private Set innerResolve(Context context, List expressions, Indi return result; } - private static boolean unavailableIgnoredOrExists(IndicesOptions options, MetaData metaData, String expression) { - return options.ignoreUnavailable() || aliasOrIndexExists(options, metaData, expression); - } - private static boolean aliasOrIndexExists(IndicesOptions options, MetaData metaData, String expression) { AliasOrIndex aliasOrIndex = metaData.getAliasAndIndexLookup().get(expression); //treat aliases as unavailable indices when ignoreAliases is set to true (e.g. delete index and update aliases api) return aliasOrIndex != null && (options.ignoreAliases() == false || aliasOrIndex.isAlias() == false); } - private static IndexNotFoundException infe(String expression) { + private static IndexNotFoundException indexNotFoundException(String expression) { IndexNotFoundException infe = new IndexNotFoundException(expression); infe.setResources("index_or_alias", expression); return infe; diff --git a/core/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java b/core/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java index 9526b5b97e6eb..8bf074be551b1 100644 --- a/core/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java +++ b/core/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java @@ -33,11 +33,9 @@ import org.elasticsearch.cluster.metadata.AliasOrIndex; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.StopWatch; -import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.rest.action.admin.indices.AliasesNotFoundException; @@ -442,8 +440,10 @@ public void testDeleteAliases() throws Exception { assertTrue(admin().indices().prepareAliasesExist("foo").get().exists()); assertFalse(admin().indices().prepareAliasesExist("foo").setIndices("foo_foo").get().exists()); assertTrue(admin().indices().prepareAliasesExist("foo").setIndices("bar_bar").get().exists()); - expectThrows(IndexNotFoundException.class, () -> admin().indices().prepareAliases() + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> admin().indices().prepareAliases() .addAliasAction(AliasActions.remove().index("foo").alias("foo")).execute().actionGet()); + assertEquals("The provided expression [foo] matches an alias, specify the corresponding concrete indices instead.", + iae.getMessage()); } public void testWaitForAliasCreationMultipleShards() throws Exception { @@ -824,10 +824,10 @@ public void testAliasesCanBeAddedToIndicesOnly() throws Exception { logger.info("--> adding [week_20] alias to [2017-05-20]"); assertAcked(admin().indices().prepareAliases().addAlias("2017-05-20", "week_20")); - IndexNotFoundException infe = expectThrows(IndexNotFoundException.class, () -> admin().indices().prepareAliases() + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> admin().indices().prepareAliases() .addAliasAction(AliasActions.add().index("week_20").alias("tmp")).execute().actionGet()); - assertEquals("week_20", infe.getIndex().getName()); - + assertEquals("The provided expression [week_20] matches an alias, specify the corresponding concrete indices instead.", + iae.getMessage()); assertAcked(admin().indices().prepareAliases().addAliasAction(AliasActions.add().index("2017-05-20").alias("tmp")).execute().get()); } @@ -916,8 +916,10 @@ public void testAliasActionRemoveIndex() throws InterruptedException, ExecutionE assertAcked(admin().indices().prepareAliases().addAlias("foo_foo", "foo")); assertAcked(admin().indices().prepareAliases().addAlias("bar_bar", "foo")); - expectThrows(IndexNotFoundException.class, + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> client().admin().indices().prepareAliases().removeIndex("foo").execute().actionGet()); + assertEquals("The provided expression [foo] matches an alias, specify the corresponding concrete indices instead.", + iae.getMessage()); assertAcked(client().admin().indices().prepareAliases().removeIndex("foo*").execute().get()); assertFalse(client().admin().indices().prepareExists("foo_foo").execute().actionGet().isExists()); diff --git a/core/src/test/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolverTests.java b/core/src/test/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolverTests.java index 0f543daa62693..5e04714552248 100644 --- a/core/src/test/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolverTests.java +++ b/core/src/test/java/org/elasticsearch/cluster/metadata/IndexNameExpressionResolverTests.java @@ -657,9 +657,10 @@ public void testConcreteIndicesWildcardAndAliases() { assertEquals(1, indexNamesIndexWildcard.length); assertEquals("foo_foo", indexNamesIndexWildcard[0]); - IndexNotFoundException infe = expectThrows(IndexNotFoundException.class, + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, ignoreAliasesOptions, "foo")); - assertThat(infe.getIndex().getName(), equalTo("foo")); + assertEquals("The provided expression [foo] matches an alias, specify the corresponding concrete indices instead.", + iae.getMessage()); // when ignoreAliases option is not set, concreteIndexNames resolves the provided // expressions against the defined indices and aliases @@ -1005,11 +1006,13 @@ public void testDeleteIndexIgnoresAliases() { IndexNotFoundException infe = expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, new DeleteIndexRequest("does_not_exist"))); assertEquals("does_not_exist", infe.getIndex().getName()); + assertEquals("no such index", infe.getMessage()); } { - IndexNotFoundException infe = expectThrows(IndexNotFoundException.class, + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, new DeleteIndexRequest("test-alias"))); - assertEquals("test-alias", infe.getIndex().getName()); + assertEquals("The provided expression [test-alias] matches an alias, " + + "specify the corresponding concrete indices instead.", iae.getMessage()); } { DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("test-alias"); @@ -1049,11 +1052,16 @@ public void testIndicesAliasesRequestIgnoresAliases() { ClusterState state = ClusterState.builder(new ClusterName("_name")).metaData(mdBuilder).build(); { IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.add().index("test-alias"); - expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions)); + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, + () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions)); + assertEquals("The provided expression [test-alias] matches an alias, " + + "specify the corresponding concrete indices instead.", iae.getMessage()); } { IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.add().index("test-a*"); - expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions)); + IndexNotFoundException infe = expectThrows(IndexNotFoundException.class, + () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions)); + assertEquals("test-a*", infe.getIndex().getName()); } { IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.add().index("test-index"); @@ -1069,11 +1077,16 @@ public void testIndicesAliasesRequestIgnoresAliases() { } { IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.remove().index("test-alias"); - expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions)); + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, + () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions)); + assertEquals("The provided expression [test-alias] matches an alias, " + + "specify the corresponding concrete indices instead.", iae.getMessage()); } { IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.remove().index("test-a*"); - expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions)); + IndexNotFoundException infe = expectThrows(IndexNotFoundException.class, + () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions)); + assertEquals("test-a*", infe.getIndex().getName()); } { IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.remove().index("test-index"); @@ -1089,11 +1102,16 @@ public void testIndicesAliasesRequestIgnoresAliases() { } { IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.removeIndex().index("test-alias"); - expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions)); + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, + () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions)); + assertEquals("The provided expression [test-alias] matches an alias, " + + "specify the corresponding concrete indices instead.", iae.getMessage()); } { IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.removeIndex().index("test-a*"); - expectThrows(IndexNotFoundException.class, () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions)); + IndexNotFoundException infe = expectThrows(IndexNotFoundException.class, + () -> indexNameExpressionResolver.concreteIndexNames(state, aliasActions)); + assertEquals("test-a*", infe.getIndex().getName()); } { IndicesAliasesRequest.AliasActions aliasActions = IndicesAliasesRequest.AliasActions.removeIndex().index("test-index"); diff --git a/core/src/test/java/org/elasticsearch/cluster/metadata/WildcardExpressionResolverTests.java b/core/src/test/java/org/elasticsearch/cluster/metadata/WildcardExpressionResolverTests.java index e918f2acd4f36..cb2913e5820e1 100644 --- a/core/src/test/java/org/elasticsearch/cluster/metadata/WildcardExpressionResolverTests.java +++ b/core/src/test/java/org/elasticsearch/cluster/metadata/WildcardExpressionResolverTests.java @@ -24,11 +24,16 @@ import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetaData.State; +import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.test.ESTestCase; import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Set; import static org.elasticsearch.common.util.set.Sets.newHashSet; +import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.equalTo; public class WildcardExpressionResolverTests extends ESTestCase { @@ -42,13 +47,13 @@ public void testConvertWildcardsJustIndicesTests() { IndexNameExpressionResolver.WildcardExpressionResolver resolver = new IndexNameExpressionResolver.WildcardExpressionResolver(); IndexNameExpressionResolver.Context context = new IndexNameExpressionResolver.Context(state, IndicesOptions.lenientExpandOpen()); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testXXX"))), equalTo(newHashSet("testXXX"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("testXXX"))), equalTo(newHashSet("testXXX"))); assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testXXX", "testYYY"))), equalTo(newHashSet("testXXX", "testYYY"))); assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testXXX", "ku*"))), equalTo(newHashSet("testXXX", "kuku"))); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("test*"))), equalTo(newHashSet("testXXX", "testXYY", "testYYY"))); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testX*"))), equalTo(newHashSet("testXXX", "testXYY"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("test*"))), equalTo(newHashSet("testXXX", "testXYY", "testYYY"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("testX*"))), equalTo(newHashSet("testXXX", "testXYY"))); assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testX*", "kuku"))), equalTo(newHashSet("testXXX", "testXYY", "kuku"))); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("*"))), equalTo(newHashSet("testXXX", "testXYY", "testYYY", "kuku"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("*"))), equalTo(newHashSet("testXXX", "testXYY", "testYYY", "kuku"))); assertThat(newHashSet(resolver.resolve(context, Arrays.asList("*", "-kuku"))), equalTo(newHashSet("testXXX", "testXYY", "testYYY"))); assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testXXX", "testYYY"))), equalTo(newHashSet("testXXX", "testYYY"))); assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testXXX", "-testXXX"))), equalTo(newHashSet("testXXX", "-testXXX"))); @@ -67,7 +72,7 @@ public void testConvertWildcardsTests() { IndexNameExpressionResolver.Context context = new IndexNameExpressionResolver.Context(state, IndicesOptions.lenientExpandOpen()); assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testYY*", "alias*"))), equalTo(newHashSet("testXXX", "testXYY", "testYYY"))); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("-kuku"))), equalTo(newHashSet("-kuku"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("-kuku"))), equalTo(newHashSet("-kuku"))); assertThat(newHashSet(resolver.resolve(context, Arrays.asList("test*", "-testYYY"))), equalTo(newHashSet("testXXX", "testXYY"))); assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testX*", "testYYY"))), equalTo(newHashSet("testXXX", "testXYY", "testYYY"))); assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testYYY", "testX*"))), equalTo(newHashSet("testXXX", "testXYY", "testYYY"))); @@ -85,11 +90,11 @@ public void testConvertWildcardsOpenClosedIndicesTests() { IndexNameExpressionResolver.WildcardExpressionResolver resolver = new IndexNameExpressionResolver.WildcardExpressionResolver(); IndexNameExpressionResolver.Context context = new IndexNameExpressionResolver.Context(state, IndicesOptions.fromOptions(true, true, true, true)); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testX*"))), equalTo(newHashSet("testXXX", "testXXY", "testXYY"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("testX*"))), equalTo(newHashSet("testXXX", "testXXY", "testXYY"))); context = new IndexNameExpressionResolver.Context(state, IndicesOptions.fromOptions(true, true, false, true)); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testX*"))), equalTo(newHashSet("testXYY"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("testX*"))), equalTo(newHashSet("testXYY"))); context = new IndexNameExpressionResolver.Context(state, IndicesOptions.fromOptions(true, true, true, false)); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("testX*"))), equalTo(newHashSet("testXXX", "testXXY"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("testX*"))), equalTo(newHashSet("testXXX", "testXXY"))); } // issue #13334 @@ -106,12 +111,12 @@ public void testMultipleWildcards() { IndexNameExpressionResolver.WildcardExpressionResolver resolver = new IndexNameExpressionResolver.WildcardExpressionResolver(); IndexNameExpressionResolver.Context context = new IndexNameExpressionResolver.Context(state, IndicesOptions.lenientExpandOpen()); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("test*X*"))), equalTo(newHashSet("testXXX", "testXXY", "testXYY"))); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("test*X*Y"))), equalTo(newHashSet("testXXY", "testXYY"))); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("kuku*Y*"))), equalTo(newHashSet("kukuYYY"))); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("*Y*"))), equalTo(newHashSet("testXXY", "testXYY", "testYYY", "kukuYYY"))); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("test*Y*X"))).size(), equalTo(0)); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("*Y*X"))).size(), equalTo(0)); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("test*X*"))), equalTo(newHashSet("testXXX", "testXXY", "testXYY"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("test*X*Y"))), equalTo(newHashSet("testXXY", "testXYY"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("kuku*Y*"))), equalTo(newHashSet("kukuYYY"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("*Y*"))), equalTo(newHashSet("testXXY", "testXYY", "testYYY", "kukuYYY"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("test*Y*X"))).size(), equalTo(0)); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("*Y*X"))).size(), equalTo(0)); } public void testAll() { @@ -123,13 +128,75 @@ public void testAll() { IndexNameExpressionResolver.WildcardExpressionResolver resolver = new IndexNameExpressionResolver.WildcardExpressionResolver(); IndexNameExpressionResolver.Context context = new IndexNameExpressionResolver.Context(state, IndicesOptions.lenientExpandOpen()); - assertThat(newHashSet(resolver.resolve(context, Arrays.asList("_all"))), equalTo(newHashSet("testXXX", "testXYY", "testYYY"))); + assertThat(newHashSet(resolver.resolve(context, Collections.singletonList("_all"))), equalTo(newHashSet("testXXX", "testXYY", "testYYY"))); } - public void testConcreteIndicesWildcardAndAliases() { + public void testResolveAliases() { MetaData.Builder mdBuilder = MetaData.builder() - .put(indexBuilder("foo_foo").state(State.OPEN).putAlias(AliasMetaData.builder("foo"))) - .put(indexBuilder("bar_bar").state(State.OPEN).putAlias(AliasMetaData.builder("foo"))); + .put(indexBuilder("foo_foo").state(State.OPEN)) + .put(indexBuilder("bar_bar").state(State.OPEN)) + .put(indexBuilder("foo_index").state(State.OPEN).putAlias(AliasMetaData.builder("foo_alias"))) + .put(indexBuilder("bar_index").state(State.OPEN).putAlias(AliasMetaData.builder("foo_alias"))); + ClusterState state = ClusterState.builder(new ClusterName("_name")).metaData(mdBuilder).build(); + IndexNameExpressionResolver.WildcardExpressionResolver resolver = new IndexNameExpressionResolver.WildcardExpressionResolver(); + // when ignoreAliases option is not set, WildcardExpressionResolver resolves the provided + // expressions against the defined indices and aliases + IndicesOptions indicesAndAliasesOptions = IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), true, false, true, false, false); + IndexNameExpressionResolver.Context indicesAndAliasesContext = new IndexNameExpressionResolver.Context(state, indicesAndAliasesOptions); + // ignoreAliases option is set, WildcardExpressionResolver throws error when + IndicesOptions skipAliasesIndicesOptions = IndicesOptions.fromOptions(true, true, true, false, true, false, true); + IndexNameExpressionResolver.Context skipAliasesLenientContext = new IndexNameExpressionResolver.Context(state, skipAliasesIndicesOptions); + // ignoreAliases option is set, WildcardExpressionResolver resolves the provided expressions only against the defined indices + IndicesOptions errorOnAliasIndicesOptions = IndicesOptions.fromOptions(false, false, true, false, true, false, true); + IndexNameExpressionResolver.Context skipAliasesStrictContext = new IndexNameExpressionResolver.Context(state, errorOnAliasIndicesOptions); + + { + List indices = resolver.resolve(indicesAndAliasesContext, Collections.singletonList("foo_a*")); + assertThat(indices, containsInAnyOrder("foo_index", "bar_index")); + } + { + List indices = resolver.resolve(skipAliasesLenientContext, Collections.singletonList("foo_a*")); + assertEquals(0, indices.size()); + } + { + IndexNotFoundException infe = expectThrows(IndexNotFoundException.class, + () -> resolver.resolve(skipAliasesStrictContext, Collections.singletonList("foo_a*"))); + assertEquals("foo_a*", infe.getIndex().getName()); + } + { + List indices = resolver.resolve(indicesAndAliasesContext, Collections.singletonList("foo*")); + assertThat(indices, containsInAnyOrder("foo_foo", "foo_index", "bar_index")); + } + { + List indices = resolver.resolve(skipAliasesLenientContext, Collections.singletonList("foo*")); + assertThat(indices, containsInAnyOrder("foo_foo", "foo_index")); + } + { + List indices = resolver.resolve(skipAliasesStrictContext, Collections.singletonList("foo*")); + assertThat(indices, containsInAnyOrder("foo_foo", "foo_index")); + } + { + List indices = resolver.resolve(indicesAndAliasesContext, Collections.singletonList("foo_alias")); + assertThat(indices, containsInAnyOrder("foo_alias")); + } + { + List indices = resolver.resolve(skipAliasesLenientContext, Collections.singletonList("foo_alias")); + assertThat(indices, containsInAnyOrder("foo_alias")); + } + { + IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, + () -> resolver.resolve(skipAliasesStrictContext, Collections.singletonList("foo_alias"))); + assertEquals("The provided expression [foo_alias] matches an alias, " + + "specify the corresponding concrete indices instead.", iae.getMessage()); + } + } + + public void testMatchesConcreteIndicesWildcardAndAliases() { + MetaData.Builder mdBuilder = MetaData.builder() + .put(indexBuilder("foo_foo").state(State.OPEN)) + .put(indexBuilder("bar_bar").state(State.OPEN)) + .put(indexBuilder("foo_index").state(State.OPEN).putAlias(AliasMetaData.builder("foo_alias"))) + .put(indexBuilder("bar_index").state(State.OPEN).putAlias(AliasMetaData.builder("foo_alias"))); ClusterState state = ClusterState.builder(new ClusterName("_name")).metaData(mdBuilder).build(); // when ignoreAliases option is not set, WildcardExpressionResolver resolves the provided @@ -142,44 +209,39 @@ public void testConcreteIndicesWildcardAndAliases() { IndicesOptions onlyIndicesOptions = IndicesOptions.fromOptions(false, false, true, false, true, false, true); IndexNameExpressionResolver.Context onlyIndicesContext = new IndexNameExpressionResolver.Context(state, onlyIndicesOptions); - assertThat( - IndexNameExpressionResolver.WildcardExpressionResolver - .matches(indicesAndAliasesContext, state.getMetaData(), "*").keySet(), - equalTo(newHashSet("bar_bar", "foo_foo", "foo"))); - assertThat( - IndexNameExpressionResolver.WildcardExpressionResolver - .matches(onlyIndicesContext, state.getMetaData(), "*").keySet(), - equalTo(newHashSet("bar_bar", "foo_foo"))); - - assertThat( - IndexNameExpressionResolver.WildcardExpressionResolver - .matches(indicesAndAliasesContext, state.getMetaData(), "foo*").keySet(), - equalTo(newHashSet("foo", "foo_foo"))); - assertThat( - IndexNameExpressionResolver.WildcardExpressionResolver - .matches(onlyIndicesContext, state.getMetaData(), "foo*").keySet(), - equalTo(newHashSet("foo_foo"))); - - assertThat( - IndexNameExpressionResolver.WildcardExpressionResolver - .matches(indicesAndAliasesContext, state.getMetaData(), "f*o").keySet(), - equalTo(newHashSet("foo", "foo_foo"))); - assertThat( - IndexNameExpressionResolver.WildcardExpressionResolver - .matches(onlyIndicesContext, state.getMetaData(), "f*o").keySet(), - equalTo(newHashSet("foo_foo"))); - - assertThat( - IndexNameExpressionResolver.WildcardExpressionResolver - .matches(indicesAndAliasesContext, state.getMetaData(), "foo").keySet(), - equalTo(newHashSet("foo"))); - assertThat( - IndexNameExpressionResolver.WildcardExpressionResolver - .matches(onlyIndicesContext, state.getMetaData(), "foo").keySet(), - equalTo(newHashSet())); + { + Set matches = IndexNameExpressionResolver.WildcardExpressionResolver.matches(indicesAndAliasesContext, + state.getMetaData(), "*").keySet(); + assertEquals(newHashSet("bar_bar", "foo_foo", "foo_index", "bar_index", "foo_alias"), matches); + } + { + Set matches = IndexNameExpressionResolver.WildcardExpressionResolver.matches(onlyIndicesContext, + state.getMetaData(), "*").keySet(); + assertEquals(newHashSet("bar_bar", "foo_foo", "foo_index", "bar_index"), matches); + } + { + Set matches = IndexNameExpressionResolver.WildcardExpressionResolver.matches(indicesAndAliasesContext, + state.getMetaData(), "foo*").keySet(); + assertEquals(newHashSet("foo_foo", "foo_index", "foo_alias"), matches); + } + { + Set matches = IndexNameExpressionResolver.WildcardExpressionResolver.matches(onlyIndicesContext, + state.getMetaData(), "foo*").keySet(); + assertEquals(newHashSet("foo_foo", "foo_index"), matches); + } + { + Set matches = IndexNameExpressionResolver.WildcardExpressionResolver.matches(indicesAndAliasesContext, + state.getMetaData(), "foo_alias").keySet(); + assertEquals(newHashSet("foo_alias"), matches); + } + { + Set matches = IndexNameExpressionResolver.WildcardExpressionResolver.matches(onlyIndicesContext, + state.getMetaData(), "foo_alias").keySet(); + assertEquals(newHashSet(), matches); + } } - private IndexMetaData.Builder indexBuilder(String index) { + private static IndexMetaData.Builder indexBuilder(String index) { return IndexMetaData.builder(index).settings(settings(Version.CURRENT).put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1).put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)); } } diff --git a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.delete/10_basic.yml b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.delete/10_basic.yml index 29cd2e8b5d2b8..40486da9e7e76 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/test/indices.delete/10_basic.yml +++ b/rest-api-spec/src/main/resources/rest-api-spec/test/indices.delete/10_basic.yml @@ -14,7 +14,7 @@ setup: version: " - 5.99.0" reason: delete index doesn't support aliases only from 6.0.0 on - do: - catch: missing + catch: request indices.delete: index: alias - do: @@ -42,7 +42,7 @@ setup: version: " - 5.99.0" reason: delete index doesn't support aliases only from 6.0.0 on - do: - catch: missing + catch: request indices.delete: index: alias,index2 - do: