diff --git a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java index 33e4f57c1c3..8725b4687df 100644 --- a/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java +++ b/modules/elasticsearch/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java @@ -19,16 +19,28 @@ package org.elasticsearch.cluster.metadata; +import org.elasticsearch.ElasticSearchIllegalArgumentException; import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ProcessedClusterStateUpdateTask; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.collect.Lists; +import org.elasticsearch.common.collect.Maps; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.Index; +import org.elasticsearch.index.query.xcontent.XContentIndexQueryParser; +import org.elasticsearch.index.service.IndexService; import org.elasticsearch.indices.IndexMissingException; +import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.InvalidAliasNameException; +import java.util.List; +import java.util.Map; + import static org.elasticsearch.cluster.ClusterState.*; import static org.elasticsearch.cluster.metadata.IndexMetaData.*; import static org.elasticsearch.cluster.metadata.MetaData.*; @@ -40,9 +52,12 @@ public class MetaDataIndexAliasesService extends AbstractComponent { private final ClusterService clusterService; - @Inject public MetaDataIndexAliasesService(Settings settings, ClusterService clusterService) { + private final IndicesService indicesService; + + @Inject public MetaDataIndexAliasesService(Settings settings, ClusterService clusterService, IndicesService indicesService) { super(settings); this.clusterService = clusterService; + this.indicesService = indicesService; } public void indicesAliases(final Request request, final Listener listener) { @@ -60,22 +75,58 @@ public class MetaDataIndexAliasesService extends AbstractComponent { } } - MetaData.Builder builder = newMetaDataBuilder().metaData(currentState.metaData()); - for (AliasAction aliasAction : request.actions) { - IndexMetaData indexMetaData = builder.get(aliasAction.index()); - if (indexMetaData == null) { - throw new IndexMissingException(new Index(aliasAction.index())); - } - IndexMetaData.Builder indexMetaDataBuilder = newIndexMetaDataBuilder(indexMetaData); - if (aliasAction.actionType() == AliasAction.Type.ADD) { - indexMetaDataBuilder.putAlias(AliasMetaData.newAliasMetaDataBuilder(aliasAction.alias()).filter(aliasAction.filter()).build()); - } else if (aliasAction.actionType() == AliasAction.Type.REMOVE) { - indexMetaDataBuilder.removerAlias(aliasAction.alias()); - } + List indicesToClose = Lists.newArrayList(); + Map indices = Maps.newHashMap(); + try { + MetaData.Builder builder = newMetaDataBuilder().metaData(currentState.metaData()); + for (AliasAction aliasAction : request.actions) { + IndexMetaData indexMetaData = builder.get(aliasAction.index()); + if (indexMetaData == null) { + throw new IndexMissingException(new Index(aliasAction.index())); + } + IndexMetaData.Builder indexMetaDataBuilder = newIndexMetaDataBuilder(indexMetaData); + if (aliasAction.actionType() == AliasAction.Type.ADD) { + String filter = aliasAction.filter(); + if (Strings.hasLength(filter)) { + // parse the filter, in order to validate it + IndexService indexService = indices.get(indexMetaData.index()); + if (indexService == null) { + indexService = indicesService.indexService(indexMetaData.index()); + if (indexService == null) { + // temporarily create the index so we have can parse the filter + indexService = indicesService.createIndex(indexMetaData.index(), indexMetaData.settings(), currentState.nodes().localNode().id()); + indicesToClose.add(indexMetaData.index()); + } + indices.put(indexMetaData.index(), indexService); + } - builder.put(indexMetaDataBuilder); + // now, parse the filter + XContentIndexQueryParser indexQueryParser = (XContentIndexQueryParser) indexService.queryParserService().defaultIndexQueryParser(); + try { + XContentParser parser = XContentFactory.xContent(filter).createParser(filter); + try { + indexQueryParser.parseInnerFilter(parser); + } finally { + parser.close(); + } + } catch (Exception e) { + listener.onFailure(new ElasticSearchIllegalArgumentException("failed to parse filter for [" + aliasAction.alias() + "]", e)); + return currentState; + } + } + indexMetaDataBuilder.putAlias(AliasMetaData.newAliasMetaDataBuilder(aliasAction.alias()).filter(filter).build()); + } else if (aliasAction.actionType() == AliasAction.Type.REMOVE) { + indexMetaDataBuilder.removerAlias(aliasAction.alias()); + } + + builder.put(indexMetaDataBuilder); + } + return newClusterStateBuilder().state(currentState).metaData(builder).build(); + } finally { + for (String index : indicesToClose) { + indicesService.cleanIndex(index, "created for mapping processing"); + } } - return newClusterStateBuilder().state(currentState).metaData(builder).build(); } @Override public void clusterStateProcessed(ClusterState clusterState) { diff --git a/modules/test/integration/src/test/java/org/elasticsearch/test/integration/aliases/IndexAliasesTests.java b/modules/test/integration/src/test/java/org/elasticsearch/test/integration/aliases/IndexAliasesTests.java index 6ecddd7ba55..7923fe34bd7 100644 --- a/modules/test/integration/src/test/java/org/elasticsearch/test/integration/aliases/IndexAliasesTests.java +++ b/modules/test/integration/src/test/java/org/elasticsearch/test/integration/aliases/IndexAliasesTests.java @@ -32,14 +32,14 @@ import org.elasticsearch.indices.IndexMissingException; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.test.integration.AbstractNodesTests; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.BeforeMethod; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import java.util.Set; import static org.elasticsearch.client.Requests.*; -import static org.elasticsearch.common.collect.Sets.newHashSet; +import static org.elasticsearch.common.collect.Sets.*; import static org.elasticsearch.index.query.xcontent.FilterBuilders.*; import static org.hamcrest.MatcherAssert.*; import static org.hamcrest.Matchers.*; @@ -53,14 +53,14 @@ public class IndexAliasesTests extends AbstractNodesTests { protected Client client1; protected Client client2; - @BeforeMethod public void startNodes() { + @BeforeClass public void startNodes() { startNode("server1"); startNode("server2"); client1 = getClient1(); client2 = getClient2(); } - @AfterMethod public void closeNodes() { + @AfterClass public void closeNodes() { client1.close(); client2.close(); closeAllNodes(); @@ -74,8 +74,10 @@ public class IndexAliasesTests extends AbstractNodesTests { return client("server2"); } - @Test public void testAliases() throws Exception { + // delete all indices + client1.admin().indices().prepareDelete().execute().actionGet(); + logger.info("--> creating index [test]"); client1.admin().indices().create(createIndexRequest("test")).actionGet(); @@ -119,7 +121,32 @@ public class IndexAliasesTests extends AbstractNodesTests { assertThat(indexResponse.index(), equalTo("test_x")); } + @Test public void testFailedFilter() throws Exception { + // delete all indices + client1.admin().indices().prepareDelete().execute().actionGet(); + + logger.info("--> creating index [test]"); + client1.admin().indices().create(createIndexRequest("test")).actionGet(); + + logger.info("--> running cluster_health"); + ClusterHealthResponse clusterHealth = client1.admin().cluster().health(clusterHealthRequest().waitForGreenStatus()).actionGet(); + logger.info("--> done cluster_health, status " + clusterHealth.status()); + assertThat(clusterHealth.timedOut(), equalTo(false)); + assertThat(clusterHealth.status(), equalTo(ClusterHealthStatus.GREEN)); + + try { + logger.info("--> aliasing index [test] with [alias1] and filter [t]"); + client1.admin().indices().prepareAliases().addAlias("test", "alias1", "{ t }").execute().actionGet(); + assert false; + } catch (Exception e) { + // all is well + } + } + @Test public void testFilteringAliases() throws Exception { + // delete all indices + client1.admin().indices().prepareDelete().execute().actionGet(); + logger.info("--> creating index [test]"); client1.admin().indices().create(createIndexRequest("test")).actionGet(); @@ -143,6 +170,9 @@ public class IndexAliasesTests extends AbstractNodesTests { } @Test public void testSearchingFilteringAliasesSingleIndex() throws Exception { + // delete all indices + client1.admin().indices().prepareDelete().execute().actionGet(); + logger.info("--> creating index [test]"); client1.admin().indices().create(createIndexRequest("test")).actionGet(); @@ -190,6 +220,9 @@ public class IndexAliasesTests extends AbstractNodesTests { } @Test public void testSearchingFilteringAliasesTwoIndices() throws Exception { + // delete all indices + client1.admin().indices().prepareDelete().execute().actionGet(); + logger.info("--> creating index [test1]"); client1.admin().indices().create(createIndexRequest("test1")).actionGet(); @@ -258,6 +291,9 @@ public class IndexAliasesTests extends AbstractNodesTests { } @Test public void testSearchingFilteringAliasesMultipleIndices() throws Exception { + // delete all indices + client1.admin().indices().prepareDelete().execute().actionGet(); + logger.info("--> creating indices"); client1.admin().indices().create(createIndexRequest("test1")).actionGet(); client1.admin().indices().create(createIndexRequest("test2")).actionGet(); @@ -325,6 +361,9 @@ public class IndexAliasesTests extends AbstractNodesTests { } @Test public void testDeletingByQueryFilteringAliases() throws Exception { + // delete all indices + client1.admin().indices().prepareDelete().execute().actionGet(); + logger.info("--> creating index [test1]"); client1.admin().indices().create(createIndexRequest("test1")).actionGet();