/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.indices.template;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.indices.InvalidAliasNameException;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.test.ESIntegTestCase;
import org.junit.After;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.elasticsearch.action.support.WriteRequest.RefreshPolicy.IMMEDIATE;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertThrows;
import static org.hamcrest.Matchers.anyOf;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
public class SimpleIndexTemplateIT extends ESIntegTestCase {
@After
public void cleanupTemplates() {
client().admin().indices().prepareDeleteTemplate("*").get();
}
public void testSimpleIndexTemplateTests() throws Exception {
// clean all templates setup by the framework.
client().admin().indices().prepareDeleteTemplate("*").get();
// check get all templates on an empty index.
GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates().get();
assertThat(response.getIndexTemplates(), empty());
client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.setSettings(indexSettings())
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
.startObject("field2").field("type", "keyword").field("store", true).endObject()
.endObject().endObject().endObject())
.get();
client().admin().indices().preparePutTemplate("template_2")
.setPatterns(Collections.singletonList("test*"))
.setSettings(indexSettings())
.setOrder(1)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field2").field("type", "text").field("store", false).endObject()
.endObject().endObject().endObject())
.get();
// test create param
assertThrows(client().admin().indices().preparePutTemplate("template_2")
.setPatterns(Collections.singletonList("test*"))
.setSettings(indexSettings())
.setCreate(true)
.setOrder(1)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field2").field("type", "text").field("store", false).endObject()
.endObject().endObject().endObject())
, IllegalArgumentException.class
);
response = client().admin().indices().prepareGetTemplates().get();
assertThat(response.getIndexTemplates(), hasSize(2));
// index something into test_index, will match on both templates
client().prepareIndex("test_index", "type1", "1")
.setSource("field1", "value1", "field2", "value 2")
.setRefreshPolicy(IMMEDIATE).get();
ensureGreen();
SearchResponse searchResponse = client().prepareSearch("test_index")
.setQuery(termQuery("field1", "value1"))
.addStoredField("field1").addStoredField("field2")
.execute().actionGet();
assertHitCount(searchResponse, 1);
assertThat(searchResponse.getHits().getAt(0).field("field1").getValue().toString(), equalTo("value1"));
// field2 is not stored.
assertThat(searchResponse.getHits().getAt(0).field("field2"), nullValue());
client().prepareIndex("text_index", "type1", "1")
.setSource("field1", "value1", "field2", "value 2")
.setRefreshPolicy(IMMEDIATE).get();
ensureGreen();
// now only match on one template (template_1)
searchResponse = client().prepareSearch("text_index")
.setQuery(termQuery("field1", "value1"))
.addStoredField("field1").addStoredField("field2")
.execute().actionGet();
if (searchResponse.getFailedShards() > 0) {
logger.warn("failed search {}", Arrays.toString(searchResponse.getShardFailures()));
}
assertHitCount(searchResponse, 1);
assertThat(searchResponse.getHits().getAt(0).field("field1").getValue().toString(), equalTo("value1"));
assertThat(searchResponse.getHits().getAt(0).field("field2").getValue().toString(), equalTo("value 2"));
}
public void testDeleteIndexTemplate() throws Exception {
final int existingTemplates = admin().cluster().prepareState().execute().actionGet().getState().metaData().templates().size();
logger.info("--> put template_1 and template_2");
client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder()
.startObject()
.startObject("type1")
.startObject("properties")
.startObject("field1")
.field("type", "text")
.field("store", true)
.endObject()
.startObject("field2")
.field("type", "text")
.field("store", true)
.endObject()
.endObject()
.endObject()
.endObject())
.execute().actionGet();
client().admin().indices().preparePutTemplate("template_2")
.setPatterns(Collections.singletonList("test*"))
.setOrder(1)
.addMapping("type1", XContentFactory.jsonBuilder()
.startObject()
.startObject("type1")
.startObject("properties")
.startObject("field2")
.field("type", "text")
.field("store", false)
.endObject()
.endObject()
.endObject()
.endObject())
.execute().actionGet();
logger.info("--> explicitly delete template_1");
admin().indices().prepareDeleteTemplate("template_1").execute().actionGet();
ClusterState state = admin().cluster().prepareState().execute().actionGet().getState();
assertThat(state.metaData().templates().size(), equalTo(1 + existingTemplates));
assertThat(state.metaData().templates().containsKey("template_2"), equalTo(true));
assertThat(state.metaData().templates().containsKey("template_1"), equalTo(false));
logger.info("--> put template_1 back");
client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
.startObject("field2").field("type", "keyword").field("store", true).endObject()
.endObject().endObject().endObject())
.execute().actionGet();
logger.info("--> delete template*");
admin().indices().prepareDeleteTemplate("template*").execute().actionGet();
assertThat(admin().cluster().prepareState().execute().actionGet().getState().metaData().templates().size(),
equalTo(existingTemplates));
logger.info("--> delete * with no templates, make sure we don't get a failure");
admin().indices().prepareDeleteTemplate("*").execute().actionGet();
assertThat(admin().cluster().prepareState().execute().actionGet().getState().metaData().templates().size(),
equalTo(0));
}
public void testThatGetIndexTemplatesWorks() throws Exception {
logger.info("--> put template_1");
client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.setVersion(123)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
.startObject("field2").field("type", "keyword").field("store", true).endObject()
.endObject().endObject().endObject())
.execute().actionGet();
logger.info("--> get template template_1");
GetIndexTemplatesResponse getTemplate1Response = client().admin().indices().prepareGetTemplates("template_1").execute().actionGet();
assertThat(getTemplate1Response.getIndexTemplates(), hasSize(1));
assertThat(getTemplate1Response.getIndexTemplates().get(0), is(notNullValue()));
assertThat(getTemplate1Response.getIndexTemplates().get(0).patterns(), is(Collections.singletonList("te*")));
assertThat(getTemplate1Response.getIndexTemplates().get(0).getOrder(), is(0));
assertThat(getTemplate1Response.getIndexTemplates().get(0).getVersion(), is(123));
logger.info("--> get non-existing-template");
GetIndexTemplatesResponse getTemplate2Response =
client().admin().indices().prepareGetTemplates("non-existing-template").execute().actionGet();
assertThat(getTemplate2Response.getIndexTemplates(), hasSize(0));
}
public void testThatGetIndexTemplatesWithSimpleRegexWorks() throws Exception {
logger.info("--> put template_1");
client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
.startObject("field2").field("type", "keyword").field("store", true).endObject()
.endObject().endObject().endObject())
.execute().actionGet();
logger.info("--> put template_2");
client().admin().indices().preparePutTemplate("template_2")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
.startObject("field2").field("type", "keyword").field("store", true).endObject()
.endObject().endObject().endObject())
.execute().actionGet();
logger.info("--> put template3");
client().admin().indices().preparePutTemplate("template3")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
.startObject("field2").field("type", "keyword").field("store", true).endObject()
.endObject().endObject().endObject())
.execute().actionGet();
logger.info("--> get template template_*");
GetIndexTemplatesResponse getTemplate1Response = client().admin().indices().prepareGetTemplates("template_*").execute().actionGet();
assertThat(getTemplate1Response.getIndexTemplates(), hasSize(2));
List<String> templateNames = new ArrayList<>();
templateNames.add(getTemplate1Response.getIndexTemplates().get(0).name());
templateNames.add(getTemplate1Response.getIndexTemplates().get(1).name());
assertThat(templateNames, containsInAnyOrder("template_1", "template_2"));
logger.info("--> get all templates");
getTemplate1Response = client().admin().indices().prepareGetTemplates("template*").execute().actionGet();
assertThat(getTemplate1Response.getIndexTemplates(), hasSize(3));
templateNames = new ArrayList<>();
templateNames.add(getTemplate1Response.getIndexTemplates().get(0).name());
templateNames.add(getTemplate1Response.getIndexTemplates().get(1).name());
templateNames.add(getTemplate1Response.getIndexTemplates().get(2).name());
assertThat(templateNames, containsInAnyOrder("template_1", "template_2", "template3"));
logger.info("--> get templates template_1 and template_2");
getTemplate1Response = client().admin().indices().prepareGetTemplates("template_1", "template_2").execute().actionGet();
assertThat(getTemplate1Response.getIndexTemplates(), hasSize(2));
templateNames = new ArrayList<>();
templateNames.add(getTemplate1Response.getIndexTemplates().get(0).name());
templateNames.add(getTemplate1Response.getIndexTemplates().get(1).name());
assertThat(templateNames, containsInAnyOrder("template_1", "template_2"));
}
public void testThatInvalidGetIndexTemplatesFails() throws Exception {
logger.info("--> get template null");
testExpectActionRequestValidationException((String[])null);
logger.info("--> get template empty");
testExpectActionRequestValidationException("");
logger.info("--> get template 'a', '', 'c'");
testExpectActionRequestValidationException("a", "", "c");
logger.info("--> get template 'a', null, 'c'");
testExpectActionRequestValidationException("a", null, "c");
}
private void testExpectActionRequestValidationException(String... names) {
assertThrows(client().admin().indices().prepareGetTemplates(names),
ActionRequestValidationException.class,
"get template with " + Arrays.toString(names));
}
public void testBrokenMapping() throws Exception {
// clean all templates setup by the framework.
client().admin().indices().prepareDeleteTemplate("*").get();
// check get all templates on an empty index.
GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates().get();
assertThat(response.getIndexTemplates(), empty());
MapperParsingException e = expectThrows( MapperParsingException.class,
() -> client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.addMapping("type1", "{\"foo\": \"abcde\"}", XContentType.JSON)
.get());
assertThat(e.getMessage(), containsString("Failed to parse mapping "));
response = client().admin().indices().prepareGetTemplates().get();
assertThat(response.getIndexTemplates(), hasSize(0));
}
public void testInvalidSettings() throws Exception {
// clean all templates setup by the framework.
client().admin().indices().prepareDeleteTemplate("*").get();
// check get all templates on an empty index.
GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates().get();
assertThat(response.getIndexTemplates(), empty());
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.setSettings(Settings.builder().put("does_not_exist", "test"))
.get());
assertEquals("unknown setting [index.does_not_exist] please check that any required plugins are" +
" installed, or check the breaking changes documentation for removed settings", e.getMessage());
response = client().admin().indices().prepareGetTemplates().get();
assertEquals(0, response.getIndexTemplates().size());
createIndex("test");
GetSettingsResponse getSettingsResponse = client().admin().indices().prepareGetSettings("test").get();
assertNull(getSettingsResponse.getIndexToSettings().get("test").getAsMap().get("index.does_not_exist"));
}
public void testIndexTemplateWithAliases() throws Exception {
client().admin().indices().preparePutTemplate("template_with_aliases")
.setPatterns(Collections.singletonList("te*"))
.addMapping("type1", "{\"type1\" : {\"properties\" : {\"value\" : {\"type\" : \"text\"}}}}", XContentType.JSON)
.addAlias(new Alias("simple_alias"))
.addAlias(new Alias("templated_alias-{index}"))
.addAlias(new Alias("filtered_alias").filter("{\"type\":{\"value\":\"type2\"}}"))
.addAlias(new Alias("complex_filtered_alias")
.filter(QueryBuilders.termsQuery("_type", "typeX", "typeY", "typeZ")))
.get();
assertAcked(prepareCreate("test_index")
.setSettings("index.mapping.single_type", false)
.addMapping("type1").addMapping("type2").addMapping("typeX").addMapping("typeY").addMapping("typeZ"));
ensureGreen();
client().prepareIndex("test_index", "type1", "1").setSource("field", "A value").get();
client().prepareIndex("test_index", "type2", "2").setSource("field", "B value").get();
client().prepareIndex("test_index", "typeX", "3").setSource("field", "C value").get();
client().prepareIndex("test_index", "typeY", "4").setSource("field", "D value").get();
client().prepareIndex("test_index", "typeZ", "5").setSource("field", "E value").get();
GetAliasesResponse getAliasesResponse = client().admin().indices().prepareGetAliases().setIndices("test_index").get();
assertThat(getAliasesResponse.getAliases().size(), equalTo(1));
assertThat(getAliasesResponse.getAliases().get("test_index").size(), equalTo(4));
refresh();
SearchResponse searchResponse = client().prepareSearch("test_index").get();
assertHitCount(searchResponse, 5L);
searchResponse = client().prepareSearch("simple_alias").get();
assertHitCount(searchResponse, 5L);
searchResponse = client().prepareSearch("templated_alias-test_index").get();
assertHitCount(searchResponse, 5L);
searchResponse = client().prepareSearch("filtered_alias").get();
assertHitCount(searchResponse, 1L);
assertThat(searchResponse.getHits().getAt(0).getType(), equalTo("type2"));
// Search the complex filter alias
searchResponse = client().prepareSearch("complex_filtered_alias").get();
assertHitCount(searchResponse, 3L);
Set<String> types = new HashSet<>();
for (SearchHit searchHit : searchResponse.getHits().getHits()) {
types.add(searchHit.getType());
}
assertThat(types.size(), equalTo(3));
assertThat(types, containsInAnyOrder("typeX", "typeY", "typeZ"));
}
public void testIndexTemplateWithAliasesInSource() {
client().admin().indices().preparePutTemplate("template_1")
.setSource(new BytesArray("{\n" +
" \"template\" : \"*\",\n" +
" \"aliases\" : {\n" +
" \"my_alias\" : {\n" +
" \"filter\" : {\n" +
" \"type\" : {\n" +
" \"value\" : \"type2\"\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}"), XContentType.JSON).get();
assertAcked(prepareCreate("test_index")
.setSettings("index.mapping.single_type", false)
.addMapping("type1").addMapping("type2"));
ensureGreen();
GetAliasesResponse getAliasesResponse = client().admin().indices().prepareGetAliases().setIndices("test_index").get();
assertThat(getAliasesResponse.getAliases().size(), equalTo(1));
assertThat(getAliasesResponse.getAliases().get("test_index").size(), equalTo(1));
client().prepareIndex("test_index", "type1", "1").setSource("field", "value1").get();
client().prepareIndex("test_index", "type2", "2").setSource("field", "value2").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test_index").get();
assertHitCount(searchResponse, 2L);
searchResponse = client().prepareSearch("my_alias").get();
assertHitCount(searchResponse, 1L);
assertThat(searchResponse.getHits().getAt(0).getType(), equalTo("type2"));
}
public void testIndexTemplateWithAliasesSource() {
client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.setAliases(
" {\n" +
" \"alias1\" : {},\n" +
" \"alias2\" : {\n" +
" \"filter\" : {\n" +
" \"type\" : {\n" +
" \"value\" : \"type2\"\n" +
" }\n" +
" }\n" +
" },\n" +
" \"alias3\" : { \"routing\" : \"1\" }" +
" }\n").get();
assertAcked(prepareCreate("test_index")
.setSettings("index.mapping.single_type", false)
.addMapping("type1").addMapping("type2"));
ensureGreen();
GetAliasesResponse getAliasesResponse = client().admin().indices().prepareGetAliases().setIndices("test_index").get();
assertThat(getAliasesResponse.getAliases().size(), equalTo(1));
assertThat(getAliasesResponse.getAliases().get("test_index").size(), equalTo(3));
client().prepareIndex("test_index", "type1", "1").setSource("field", "value1").get();
client().prepareIndex("test_index", "type2", "2").setSource("field", "value2").get();
refresh();
SearchResponse searchResponse = client().prepareSearch("test_index").get();
assertHitCount(searchResponse, 2L);
searchResponse = client().prepareSearch("alias1").get();
assertHitCount(searchResponse, 2L);
searchResponse = client().prepareSearch("alias2").get();
assertHitCount(searchResponse, 1L);
assertThat(searchResponse.getHits().getAt(0).getType(), equalTo("type2"));
}
public void testDuplicateAlias() throws Exception {
client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.addAlias(new Alias("my_alias").filter(termQuery("field", "value1")))
.addAlias(new Alias("my_alias").filter(termQuery("field", "value2")))
.get();
GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates("template_1").get();
assertThat(response.getIndexTemplates().size(), equalTo(1));
assertThat(response.getIndexTemplates().get(0).getAliases().size(), equalTo(1));
assertThat(response.getIndexTemplates().get(0).getAliases().get("my_alias").filter().string(), containsString("\"value1\""));
}
public void testAliasInvalidFilterValidJson() throws Exception {
//invalid filter but valid json: put index template works fine, fails during index creation
client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.addAlias(new Alias("invalid_alias").filter("{ \"invalid\": {} }")).get();
GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates("template_1").get();
assertThat(response.getIndexTemplates().size(), equalTo(1));
assertThat(response.getIndexTemplates().get(0).getAliases().size(), equalTo(1));
assertThat(response.getIndexTemplates().get(0).getAliases().get("invalid_alias").filter().string(), equalTo("{\"invalid\":{}}"));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> createIndex("test"));
assertThat(e.getMessage(), equalTo("failed to parse filter for alias [invalid_alias]"));
assertThat(e.getCause(), instanceOf(ParsingException.class));
assertThat(e.getCause().getMessage(), equalTo("no [query] registered for [invalid]"));
}
public void testAliasInvalidFilterInvalidJson() throws Exception {
//invalid json: put index template fails
PutIndexTemplateRequestBuilder putIndexTemplateRequestBuilder = client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.addAlias(new Alias("invalid_alias").filter("abcde"));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> putIndexTemplateRequestBuilder.get());
assertThat(e.getMessage(), equalTo("failed to parse filter for alias [invalid_alias]"));
GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates("template_1").get();
assertThat(response.getIndexTemplates().size(), equalTo(0));
}
public void testAliasNameExistingIndex() throws Exception {
createIndex("index");
client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.addAlias(new Alias("index")).get();
InvalidAliasNameException e = expectThrows(InvalidAliasNameException.class,
() -> createIndex("test"));
assertThat(e.getMessage(), equalTo("Invalid alias name [index], an index exists with the same name as the alias"));
}
public void testAliasEmptyName() throws Exception {
PutIndexTemplateRequestBuilder putIndexTemplateRequestBuilder = client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.addAlias(new Alias(" ").indexRouting("1,2,3"));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> putIndexTemplateRequestBuilder.get());
assertThat(e.getMessage(), equalTo("alias name is required"));
}
public void testAliasWithMultipleIndexRoutings() throws Exception {
PutIndexTemplateRequestBuilder putIndexTemplateRequestBuilder = client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.addAlias(new Alias("alias").indexRouting("1,2,3"));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> putIndexTemplateRequestBuilder.get());
assertThat(e.getMessage(), equalTo("alias [alias] has several index routing values associated with it"));
}
public void testMultipleAliasesPrecedence() throws Exception {
client().admin().indices().preparePutTemplate("template1")
.setPatterns(Collections.singletonList("*"))
.setOrder(0)
.addAlias(new Alias("alias1"))
.addAlias(new Alias("{index}-alias"))
.addAlias(new Alias("alias3").filter(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery("test"))))
.addAlias(new Alias("alias4")).get();
client().admin().indices().preparePutTemplate("template2")
.setPatterns(Collections.singletonList("te*"))
.setOrder(1)
.addAlias(new Alias("alias1").routing("test"))
.addAlias(new Alias("alias3")).get();
assertAcked(prepareCreate("test").addAlias(new Alias("test-alias").searchRouting("test-routing")));
ensureGreen();
GetAliasesResponse getAliasesResponse = client().admin().indices().prepareGetAliases().addIndices("test").get();
assertThat(getAliasesResponse.getAliases().get("test").size(), equalTo(4));
for (AliasMetaData aliasMetaData : getAliasesResponse.getAliases().get("test")) {
assertThat(aliasMetaData.alias(), anyOf(equalTo("alias1"), equalTo("test-alias"), equalTo("alias3"), equalTo("alias4")));
if ("alias1".equals(aliasMetaData.alias())) {
assertThat(aliasMetaData.indexRouting(), equalTo("test"));
assertThat(aliasMetaData.searchRouting(), equalTo("test"));
} else if ("alias3".equals(aliasMetaData.alias())) {
assertThat(aliasMetaData.filter(), nullValue());
} else if ("test-alias".equals(aliasMetaData.alias())) {
assertThat(aliasMetaData.indexRouting(), nullValue());
assertThat(aliasMetaData.searchRouting(), equalTo("test-routing"));
}
}
}
public void testStrictAliasParsingInIndicesCreatedViaTemplates() throws Exception {
// Indexing into a should succeed, because the field mapping for field 'field' is defined in the test mapping.
client().admin().indices().preparePutTemplate("template1")
.setPatterns(Collections.singletonList("a*"))
.setOrder(0)
.addMapping("test", "field", "type=text")
.addAlias(new Alias("alias1").filter(termQuery("field", "value"))).get();
// Indexing into b should succeed, because the field mapping for field 'field' is defined in the _default_ mapping and
// the test type exists.
client().admin().indices().preparePutTemplate("template2")
.setPatterns(Collections.singletonList("b*"))
.setOrder(0)
.addMapping("_default_", "field", "type=text")
.addMapping("test")
.addAlias(new Alias("alias2").filter(termQuery("field", "value"))).get();
// Indexing into c should succeed, because the field mapping for field 'field' is defined in the _default_ mapping.
client().admin().indices().preparePutTemplate("template3")
.setPatterns(Collections.singletonList("c*"))
.setOrder(0)
.addMapping("_default_", "field", "type=text")
.addAlias(new Alias("alias3").filter(termQuery("field", "value"))).get();
// Indexing into d index should fail, since there is field with name 'field' in the mapping
client().admin().indices().preparePutTemplate("template4")
.setPatterns(Collections.singletonList("d*"))
.setOrder(0)
.addAlias(new Alias("alias4").filter(termQuery("field", "value"))).get();
client().prepareIndex("a1", "test", "test").setSource("{}", XContentType.JSON).get();
BulkResponse response = client().prepareBulk().add(new IndexRequest("a2", "test", "test").source("{}", XContentType.JSON)).get();
assertThat(response.hasFailures(), is(false));
assertThat(response.getItems()[0].isFailed(), equalTo(false));
assertThat(response.getItems()[0].getIndex(), equalTo("a2"));
assertThat(response.getItems()[0].getType(), equalTo("test"));
assertThat(response.getItems()[0].getId(), equalTo("test"));
assertThat(response.getItems()[0].getVersion(), equalTo(1L));
client().prepareIndex("b1", "test", "test").setSource("{}", XContentType.JSON).get();
response = client().prepareBulk().add(new IndexRequest("b2", "test", "test").source("{}", XContentType.JSON)).get();
assertThat(response.hasFailures(), is(false));
assertThat(response.getItems()[0].isFailed(), equalTo(false));
assertThat(response.getItems()[0].getIndex(), equalTo("b2"));
assertThat(response.getItems()[0].getType(), equalTo("test"));
assertThat(response.getItems()[0].getId(), equalTo("test"));
assertThat(response.getItems()[0].getVersion(), equalTo(1L));
client().prepareIndex("c1", "test", "test").setSource("{}", XContentType.JSON).get();
response = client().prepareBulk().add(new IndexRequest("c2", "test", "test").source("{}", XContentType.JSON)).get();
assertThat(response.hasFailures(), is(false));
assertThat(response.getItems()[0].isFailed(), equalTo(false));
assertThat(response.getItems()[0].getIndex(), equalTo("c2"));
assertThat(response.getItems()[0].getType(), equalTo("test"));
assertThat(response.getItems()[0].getId(), equalTo("test"));
assertThat(response.getItems()[0].getVersion(), equalTo(1L));
// Before 2.0 alias filters were parsed at alias creation time, in order
// for filters to work correctly ES required that fields mentioned in those
// filters exist in the mapping.
// From 2.0 and higher alias filters are parsed at request time and therefor
// fields mentioned in filters don't need to exist in the mapping.
// So the aliases defined in the index template for this index will not fail
// even though the fields in the alias fields don't exist yet and indexing into
// an index that doesn't exist yet will succeed
client().prepareIndex("d1", "test", "test").setSource("{}", XContentType.JSON).get();
response = client().prepareBulk().add(new IndexRequest("d2", "test", "test").source("{}", XContentType.JSON)).get();
assertThat(response.hasFailures(), is(false));
assertThat(response.getItems()[0].isFailed(), equalTo(false));
assertThat(response.getItems()[0].getId(), equalTo("test"));
assertThat(response.getItems()[0].getVersion(), equalTo(1L));
}
public void testCombineTemplates() throws Exception{
// clean all templates setup by the framework.
client().admin().indices().prepareDeleteTemplate("*").get();
// check get all templates on an empty index.
GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates().get();
assertThat(response.getIndexTemplates(), empty());
//Now, a complete mapping with two separated templates is error
// base template
client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("*"))
.setSettings(
" {\n" +
" \"index\" : {\n" +
" \"analysis\" : {\n" +
" \"analyzer\" : {\n" +
" \"custom_1\" : {\n" +
" \"tokenizer\" : \"whitespace\"\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n", XContentType.JSON)
.get();
// put template using custom_1 analyzer
MapperParsingException e = expectThrows(MapperParsingException.class,
() -> client().admin().indices().preparePutTemplate("template_2")
.setPatterns(Collections.singletonList("test*"))
.setCreate(true)
.setOrder(1)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field2").field("type", "text").field("analyzer", "custom_1").endObject()
.endObject().endObject().endObject())
.get());
assertThat(e.getMessage(), containsString("analyzer [custom_1] not found for field [field2]"));
response = client().admin().indices().prepareGetTemplates().get();
assertThat(response.getIndexTemplates(), hasSize(1));
}
public void testOrderAndVersion() {
int order = randomInt();
Integer version = randomBoolean() ? randomInt() : null;
assertAcked(client().admin().indices().preparePutTemplate("versioned_template")
.setPatterns(Collections.singletonList("te*"))
.setVersion(version)
.setOrder(order)
.addMapping("test", "field", "type=text")
.get());
GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates("versioned_template").get();
assertThat(response.getIndexTemplates().size(), equalTo(1));
assertThat(response.getIndexTemplates().get(0).getVersion(), equalTo(version));
assertThat(response.getIndexTemplates().get(0).getOrder(), equalTo(order));
}
public void testMultipleTemplate() throws IOException {
client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Arrays.asList("a*", "b*"))
.setSettings(indexSettings())
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
.startObject("field2").field("type", "keyword").field("store", false).endObject()
.endObject().endObject().endObject())
.get();
client().prepareIndex("ax", "type1", "1")
.setSource("field1", "value1", "field2", "value2")
.setRefreshPolicy(IMMEDIATE).get();
client().prepareIndex("bx", "type1", "1")
.setSource("field1", "value1", "field2", "value2")
.setRefreshPolicy(IMMEDIATE).get();
ensureGreen();
// ax -> matches template
SearchResponse searchResponse = client().prepareSearch("ax")
.setQuery(termQuery("field1", "value1"))
.addStoredField("field1")
.addStoredField("field2")
.execute().actionGet();
assertHitCount(searchResponse, 1);
assertEquals("value1", searchResponse.getHits().getAt(0).field("field1").getValue().toString());
assertNull(searchResponse.getHits().getAt(0).field("field2"));
// bx -> matches template
searchResponse = client().prepareSearch("bx")
.setQuery(termQuery("field1", "value1"))
.addStoredField("field1")
.addStoredField("field2")
.execute().actionGet();
assertHitCount(searchResponse, 1);
assertEquals("value1", searchResponse.getHits().getAt(0).field("field1").getValue().toString());
assertNull(searchResponse.getHits().getAt(0).field("field2"));
}
public void testPartitionedTemplate() throws Exception {
// clean all templates setup by the framework.
client().admin().indices().prepareDeleteTemplate("*").get();
// check get all templates on an empty index.
GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates().get();
assertThat(response.getIndexTemplates(), empty());
// provide more partitions than shards
IllegalArgumentException eBadSettings = expectThrows(IllegalArgumentException.class,
() -> client().admin().indices().preparePutTemplate("template_1")
.setPatterns(Collections.singletonList("te*"))
.setSettings(Settings.builder()
.put("index.number_of_shards", "5")
.put("index.routing_partition_size", "6"))
.get());
assertThat(eBadSettings.getMessage(), containsString("partition size [6] should be a positive number "
+ "less than the number of shards [5]"));
// provide an invalid mapping for a partitioned index
IllegalArgumentException eBadMapping = expectThrows(IllegalArgumentException.class,
() -> client().admin().indices().preparePutTemplate("template_2")
.setPatterns(Collections.singletonList("te*"))
.addMapping("type", "{\"type\":{\"_routing\":{\"required\":false}}}", XContentType.JSON)
.setSettings(Settings.builder()
.put("index.number_of_shards", "6")
.put("index.routing_partition_size", "3"))
.get());
assertThat(eBadMapping.getMessage(), containsString("must have routing required for partitioned index"));
// no templates yet
response = client().admin().indices().prepareGetTemplates().get();
assertEquals(0, response.getIndexTemplates().size());
// a valid configuration that only provides the partition size
assertAcked(client().admin().indices().preparePutTemplate("just_partitions")
.setPatterns(Collections.singletonList("te*"))
.setSettings(Settings.builder()
.put("index.routing_partition_size", "6"))
.get());
// create an index with too few shards
IllegalArgumentException eBadIndex = expectThrows(IllegalArgumentException.class,
() -> prepareCreate("test_bad", Settings.builder()
.put("index.number_of_shards", 5))
.get());
assertThat(eBadIndex.getMessage(), containsString("partition size [6] should be a positive number "
+ "less than the number of shards [5]"));
// finally, create a valid index
prepareCreate("test_good", Settings.builder()
.put("index.number_of_shards", 7))
.get();
GetSettingsResponse getSettingsResponse = client().admin().indices().prepareGetSettings("test_good").get();
assertEquals("6", getSettingsResponse.getIndexToSettings().get("test_good").getAsMap().get("index.routing_partition_size"));
}
}