Allows multiple patterns to be specified for index templates (#21009)

* Allows for an array of index template patterns to be provided to an
index template, and rename the field from 'template' to 'index_pattern'.

Closes #20690
This commit is contained in:
Alexander Lin 2016-11-10 15:00:30 -08:00 committed by Nik Everett
parent 5c4392e58a
commit 0219a211d3
34 changed files with 528 additions and 188 deletions

View File

@ -20,6 +20,7 @@ package org.elasticsearch.action.admin.indices.template.put;
import org.elasticsearch.ElasticsearchGenerationException;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.admin.indices.alias.Alias;
@ -32,6 +33,8 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
@ -41,10 +44,13 @@ import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static org.elasticsearch.action.ValidateActions.addValidationError;
import static org.elasticsearch.common.settings.Settings.readSettingsFromStream;
@ -56,11 +62,15 @@ import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS;
*/
public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateRequest> implements IndicesRequest {
private static final DeprecationLogger DEPRECATION_LOGGER = new DeprecationLogger(Loggers.getLogger(PutIndexTemplateRequest.class));
public static final Version V_5_1_0 = Version.fromId(5010099);
private String name;
private String cause = "";
private String template;
private List<String> indexPatterns;
private int order;
@ -92,8 +102,8 @@ public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateR
if (name == null) {
validationException = addValidationError("name is missing", validationException);
}
if (template == null) {
validationException = addValidationError("template is missing", validationException);
if (indexPatterns == null || indexPatterns.size() == 0) {
validationException = addValidationError("pattern is missing", validationException);
}
return validationException;
}
@ -113,13 +123,13 @@ public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateR
return this.name;
}
public PutIndexTemplateRequest template(String template) {
this.template = template;
public PutIndexTemplateRequest patterns(List<String> indexPatterns) {
this.indexPatterns = indexPatterns;
return this;
}
public String template() {
return this.template;
public List<String> patterns() {
return this.indexPatterns;
}
public PutIndexTemplateRequest order(int order) {
@ -286,7 +296,20 @@ public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateR
for (Map.Entry<String, Object> entry : source.entrySet()) {
String name = entry.getKey();
if (name.equals("template")) {
template(entry.getValue().toString());
// This is needed to allow for bwc (beats, logstash) with pre-5.0 templates (#21009)
if(entry.getValue() instanceof String) {
DEPRECATION_LOGGER.deprecated("Deprecated field [template] used, replaced by [index_patterns]");
patterns(Collections.singletonList((String) entry.getValue()));
}
} else if (name.equals("index_patterns")) {
if(entry.getValue() instanceof String) {
patterns(Collections.singletonList((String) entry.getValue()));
} else if (entry.getValue() instanceof List) {
List<String> elements = ((List<?>) entry.getValue()).stream().map(Object::toString).collect(Collectors.toList());
patterns(elements);
} else {
throw new IllegalArgumentException("Malformed [template] value, should be a string or a list of strings");
}
} else if (name.equals("order")) {
order(XContentMapValues.nodeIntegerValue(entry.getValue(), order()));
} else if ("version".equals(name)) {
@ -295,7 +318,7 @@ public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateR
}
version((Integer)entry.getValue());
} else if (name.equals("settings")) {
if (!(entry.getValue() instanceof Map)) {
if ((entry.getValue() instanceof Map) == false) {
throw new IllegalArgumentException("Malformed [settings] section, should include an inner object");
}
settings((Map<String, Object>) entry.getValue());
@ -436,7 +459,7 @@ public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateR
@Override
public String[] indices() {
return new String[]{template};
return indexPatterns.toArray(new String[indexPatterns.size()]);
}
@Override
@ -449,7 +472,12 @@ public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateR
super.readFrom(in);
cause = in.readString();
name = in.readString();
template = in.readString();
if (in.getVersion().onOrAfter(V_5_1_0)) {
indexPatterns = in.readList(StreamInput::readString);
} else {
indexPatterns = Collections.singletonList(in.readString());
}
order = in.readInt();
create = in.readBoolean();
settings = readSettingsFromStream(in);
@ -475,7 +503,11 @@ public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateR
super.writeTo(out);
out.writeString(cause);
out.writeString(name);
out.writeString(template);
if (out.getVersion().onOrAfter(V_5_1_0)) {
out.writeStringList(indexPatterns);
} else {
out.writeString(indexPatterns.size() > 0 ? indexPatterns.get(0) : "");
}
out.writeInt(order);
out.writeBoolean(create);
writeSettingsToStream(settings, out);

View File

@ -25,6 +25,8 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class PutIndexTemplateRequestBuilder
@ -39,10 +41,20 @@ public class PutIndexTemplateRequestBuilder
}
/**
* Sets the template match expression that will be used to match on indices created.
* Sets the match expression that will be used to match on indices created.
*
* @deprecated Replaced by {@link #setPatterns(List)}
*/
public PutIndexTemplateRequestBuilder setTemplate(String template) {
request.template(template);
@Deprecated
public PutIndexTemplateRequestBuilder setTemplate(String indexPattern) {
return setPatterns(Collections.singletonList(indexPattern));
}
/**
* Sets the match expression that will be used to match on indices created.
*/
public PutIndexTemplateRequestBuilder setPatterns(List<String> indexPatterns) {
request.patterns(indexPatterns);
return this;
}

View File

@ -79,7 +79,7 @@ public class TransportPutIndexTemplateAction extends TransportMasterNodeAction<P
templateSettingsBuilder.put(request.settings()).normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX);
indexScopedSettings.validate(templateSettingsBuilder);
indexTemplateService.putTemplate(new MetaDataIndexTemplateService.PutRequest(cause, request.name())
.template(request.template())
.patterns(request.patterns())
.order(request.order())
.settings(templateSettingsBuilder.build())
.mappings(request.mappings())

View File

@ -395,7 +395,7 @@ public class ClusterState implements ToXContent, Diffable<ClusterState> {
IndexTemplateMetaData templateMetaData = cursor.value;
builder.startObject(templateMetaData.name());
builder.field("template", templateMetaData.template());
builder.field("index_patterns", templateMetaData.patterns());
builder.field("order", templateMetaData.order());
builder.startObject("settings");

View File

@ -29,6 +29,8 @@ import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.loader.SettingsLoader;
import org.elasticsearch.common.util.set.Sets;
@ -38,13 +40,19 @@ import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaData> {
public static final Version V_5_1_0 = Version.fromId(5010099);
public static final IndexTemplateMetaData PROTO = IndexTemplateMetaData.builder("").build();
private static final DeprecationLogger DEPRECATION_LOGGER = new DeprecationLogger(Loggers.getLogger(IndexTemplateMetaData.class));
private final String name;
@ -56,7 +64,7 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
* <pre><code>
* PUT /_template/my_template
* {
* "template": "my_index-*",
* "index_patterns": ["my_index-*"],
* "mappings": { ... },
* "version": 1
* }
@ -70,7 +78,7 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
@Nullable
private final Integer version;
private final String template;
private final List<String> patterns;
private final Settings settings;
@ -82,14 +90,14 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
private final ImmutableOpenMap<String, IndexMetaData.Custom> customs;
public IndexTemplateMetaData(String name, int order, Integer version,
String template, Settings settings,
List<String> patterns, Settings settings,
ImmutableOpenMap<String, CompressedXContent> mappings,
ImmutableOpenMap<String, AliasMetaData> aliases,
ImmutableOpenMap<String, IndexMetaData.Custom> customs) {
this.name = name;
this.order = order;
this.version = version;
this.template = template;
this.patterns= patterns;
this.settings = settings;
this.mappings = mappings;
this.aliases = aliases;
@ -122,12 +130,12 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
return this.name;
}
public String template() {
return this.template;
public List<String> patterns() {
return this.patterns;
}
public String getTemplate() {
return this.template;
public List<String> getPatterns() {
return this.patterns;
}
public Settings settings() {
@ -182,7 +190,7 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
if (!mappings.equals(that.mappings)) return false;
if (!name.equals(that.name)) return false;
if (!settings.equals(that.settings)) return false;
if (!template.equals(that.template)) return false;
if (!patterns.equals(that.patterns)) return false;
return Objects.equals(version, that.version);
}
@ -192,7 +200,7 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
int result = name.hashCode();
result = 31 * result + order;
result = 31 * result + Objects.hashCode(version);
result = 31 * result + template.hashCode();
result = 31 * result + patterns.hashCode();
result = 31 * result + settings.hashCode();
result = 31 * result + mappings.hashCode();
return result;
@ -202,7 +210,11 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
public IndexTemplateMetaData readFrom(StreamInput in) throws IOException {
Builder builder = new Builder(in.readString());
builder.order(in.readInt());
builder.template(in.readString());
if (in.getVersion().onOrAfter(V_5_1_0)) {
builder.patterns(in.readList(StreamInput::readString));
} else {
builder.patterns(Collections.singletonList(in.readString()));
}
builder.settings(Settings.readSettingsFromStream(in));
int mappingsSize = in.readVInt();
for (int i = 0; i < mappingsSize; i++) {
@ -229,7 +241,11 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
public void writeTo(StreamOutput out) throws IOException {
out.writeString(name);
out.writeInt(order);
out.writeString(template);
if (out.getVersion().onOrAfter(V_5_1_0)) {
out.writeStringList(patterns);
} else {
out.writeString(patterns.size() > 0 ? patterns.get(0) : "");
}
Settings.writeSettingsToStream(settings, out);
out.writeVInt(mappings.size());
for (ObjectObjectCursor<String, CompressedXContent> cursor : mappings) {
@ -252,7 +268,7 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
public static class Builder {
private static final Set<String> VALID_FIELDS = Sets.newHashSet("template", "order", "mappings", "settings");
private static final Set<String> VALID_FIELDS = Sets.newHashSet("template", "order", "mappings", "settings", "index_patterns");
static {
VALID_FIELDS.addAll(IndexMetaData.customPrototypes.keySet());
}
@ -263,7 +279,7 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
private Integer version;
private String template;
private List<String> indexPatterns;
private Settings settings = Settings.Builder.EMPTY_SETTINGS;
@ -284,7 +300,7 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
this.name = indexTemplateMetaData.name();
order(indexTemplateMetaData.order());
version(indexTemplateMetaData.version());
template(indexTemplateMetaData.template());
patterns(indexTemplateMetaData.patterns());
settings(indexTemplateMetaData.settings());
mappings = ImmutableOpenMap.builder(indexTemplateMetaData.mappings());
@ -302,14 +318,11 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
return this;
}
public Builder template(String template) {
this.template = template;
public Builder patterns(List<String> indexPatterns) {
this.indexPatterns = indexPatterns;
return this;
}
public String template() {
return template;
}
public Builder settings(Settings.Builder settings) {
this.settings = settings.build();
@ -361,7 +374,8 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
}
public IndexTemplateMetaData build() {
return new IndexTemplateMetaData(name, order, version, template, settings, mappings.build(), aliases.build(), customs.build());
return new IndexTemplateMetaData(name, order, version, indexPatterns, settings, mappings.build(),
aliases.build(), customs.build());
}
@SuppressWarnings("unchecked")
@ -373,7 +387,7 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
if (indexTemplateMetaData.version() != null) {
builder.field("version", indexTemplateMetaData.version());
}
builder.field("template", indexTemplateMetaData.template());
builder.field("index_patterns", indexTemplateMetaData.patterns());
builder.startObject("settings");
indexTemplateMetaData.settings().toXContent(builder, params);
@ -478,10 +492,18 @@ public class IndexTemplateMetaData extends AbstractDiffable<IndexTemplateMetaDat
}
}
}
} else if ("index_patterns".equals(currentFieldName)) {
List<String> index_patterns = new ArrayList<>();
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
index_patterns.add(parser.text());
}
builder.patterns(index_patterns);
}
} else if (token.isValue()) {
if ("template".equals(currentFieldName)) {
builder.template(parser.text());
// Prior to 5.1.0, elasticsearch only supported a single index pattern called `template` (#21009)
if("template".equals(currentFieldName)) {
DEPRECATION_LOGGER.deprecated("Deprecated field [template] used, replaced by [index_patterns]");
builder.patterns(Collections.singletonList(parser.text()));
} else if ("order".equals(currentFieldName)) {
builder.order(parser.intValue());
} else if ("version".equals(currentFieldName)) {

View File

@ -464,21 +464,24 @@ public class MetaDataCreateIndexService extends AbstractComponent {
}
private List<IndexTemplateMetaData> findTemplates(CreateIndexClusterStateUpdateRequest request, ClusterState state) throws IOException {
List<IndexTemplateMetaData> templates = new ArrayList<>();
List<IndexTemplateMetaData> templateMetadata = new ArrayList<>();
for (ObjectCursor<IndexTemplateMetaData> cursor : state.metaData().templates().values()) {
IndexTemplateMetaData template = cursor.value;
if (Regex.simpleMatch(template.template(), request.index())) {
templates.add(template);
IndexTemplateMetaData metadata = cursor.value;
for (String template: metadata.patterns()) {
if (Regex.simpleMatch(template, request.index())) {
templateMetadata.add(metadata);
break;
}
}
}
CollectionUtil.timSort(templates, new Comparator<IndexTemplateMetaData>() {
CollectionUtil.timSort(templateMetadata, new Comparator<IndexTemplateMetaData>() {
@Override
public int compare(IndexTemplateMetaData o1, IndexTemplateMetaData o2) {
return o2.order() - o1.order();
}
});
return templates;
return templateMetadata;
}
private void validate(CreateIndexClusterStateUpdateRequest request, ClusterState state) {

View File

@ -131,7 +131,7 @@ public class MetaDataIndexTemplateService extends AbstractComponent {
listener.onFailure(new IllegalArgumentException("index_template must provide a name"));
return;
}
if (request.template == null) {
if (request.indexPatterns == null) {
listener.onFailure(new IllegalArgumentException("index_template must provide a template"));
return;
}
@ -209,7 +209,7 @@ public class MetaDataIndexTemplateService extends AbstractComponent {
templateBuilder.order(request.order);
templateBuilder.version(request.version);
templateBuilder.template(request.template);
templateBuilder.patterns(request.indexPatterns);
templateBuilder.settings(request.settings);
Map<String, Map<String, Object>> mappingsForValidation = new HashMap<>();
@ -248,21 +248,23 @@ public class MetaDataIndexTemplateService extends AbstractComponent {
if (!request.name.toLowerCase(Locale.ROOT).equals(request.name)) {
validationErrors.add("name must be lower cased");
}
if (request.template.contains(" ")) {
for(String indexPattern : request.indexPatterns) {
if (indexPattern.contains(" ")) {
validationErrors.add("template must not contain a space");
}
if (request.template.contains(",")) {
if (indexPattern.contains(",")) {
validationErrors.add("template must not contain a ','");
}
if (request.template.contains("#")) {
if (indexPattern.contains("#")) {
validationErrors.add("template must not contain a '#'");
}
if (request.template.startsWith("_")) {
if (indexPattern.startsWith("_")) {
validationErrors.add("template must not start with '_'");
}
if (!Strings.validFileNameExcludingAstrix(request.template)) {
if (!Strings.validFileNameExcludingAstrix(indexPattern)) {
validationErrors.add("template must not contain the following characters " + Strings.INVALID_FILENAME_CHARS);
}
}
try {
indexScopedSettings.validate(request.settings);
@ -283,8 +285,9 @@ public class MetaDataIndexTemplateService extends AbstractComponent {
for (Alias alias : request.aliases) {
//we validate the alias only partially, as we don't know yet to which index it'll get applied to
aliasValidator.validateAliasStandalone(alias);
if (request.template.equals(alias.name())) {
throw new IllegalArgumentException("Alias [" + alias.name() + "] cannot be the same as the template pattern [" + request.template + "]");
if (request.indexPatterns.contains(alias.name())) {
throw new IllegalArgumentException("Alias [" + alias.name() +
"] cannot be the same as any pattern in [" + String.join(", ", request.indexPatterns) + "]");
}
}
}
@ -302,7 +305,7 @@ public class MetaDataIndexTemplateService extends AbstractComponent {
boolean create;
int order;
Integer version;
String template;
List<String> indexPatterns;
Settings settings = Settings.Builder.EMPTY_SETTINGS;
Map<String, String> mappings = new HashMap<>();
List<Alias> aliases = new ArrayList<>();
@ -320,8 +323,8 @@ public class MetaDataIndexTemplateService extends AbstractComponent {
return this;
}
public PutRequest template(String template) {
this.template = template;
public PutRequest patterns(List<String> indexPatterns) {
this.indexPatterns = indexPatterns;
return this;
}

View File

@ -21,7 +21,10 @@ package org.elasticsearch.rest.action.admin.indices;
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
@ -29,9 +32,13 @@ import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.AcknowledgedRestListener;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
public class RestPutIndexTemplateAction extends BaseRestHandler {
private static final DeprecationLogger DEPRECATION_LOGGER = new DeprecationLogger(Loggers.getLogger(RestPutIndexTemplateAction.class));
@Inject
public RestPutIndexTemplateAction(Settings settings, RestController controller) {
super(settings);
@ -42,7 +49,12 @@ public class RestPutIndexTemplateAction extends BaseRestHandler {
@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest(request.param("name"));
putRequest.template(request.param("template", putRequest.template()));
if (request.hasParam("template")) {
DEPRECATION_LOGGER.deprecated("Deprecated parameter[template] used, replaced by [index_patterns]");
putRequest.patterns(Collections.singletonList(request.param("template")));
} else {
putRequest.patterns(Arrays.asList(request.paramAsStringArray("index_patterns", Strings.EMPTY_ARRAY)));
}
putRequest.order(request.paramAsInt("order", putRequest.order()));
putRequest.masterNodeTimeout(request.paramAsTime("master_timeout", putRequest.masterNodeTimeout()));
putRequest.create(request.paramAsBoolean("create", false));

View File

@ -70,7 +70,7 @@ public class RestTemplatesAction extends AbstractCatAction {
Table table = new Table();
table.startHeaders();
table.addCell("name", "alias:n;desc:template name");
table.addCell("template", "alias:t;desc:template pattern string");
table.addCell("index_patterns", "alias:t;desc:template index patterns");
table.addCell("order", "alias:o;desc:template application order number");
table.addCell("version", "alias:v;desc:version");
table.endHeaders();
@ -85,7 +85,7 @@ public class RestTemplatesAction extends AbstractCatAction {
if (patternString == null || Regex.simpleMatch(patternString, indexData.name())) {
table.startRow();
table.addCell(indexData.name());
table.addCell(indexData.getTemplate());
table.addCell("[" + String.join(", ", indexData.patterns()) + "]");
table.addCell(indexData.getOrder());
table.addCell(indexData.getVersion());
table.endRow();

View File

@ -20,7 +20,9 @@
package org.elasticsearch;
import org.elasticsearch.action.ShardValidateQueryRequestTests;
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
@ -275,9 +277,11 @@ public class VersionTests extends ESTestCase {
assertUnknownVersion(V_20_0_0_UNRELEASED);
expectThrows(AssertionError.class, () -> assertUnknownVersion(Version.CURRENT));
assertUnknownVersion(AliasFilter.V_5_1_0); // once we released 5.1.0 and it's added to Version.java we need to remove this constant
assertUnknownVersion(IndexTemplateMetaData.V_5_1_0);
assertUnknownVersion(OsStats.V_5_1_0); // once we released 5.1.0 and it's added to Version.java we need to remove this constant
assertUnknownVersion(SimpleQueryStringBuilder.V_5_1_0_UNRELEASED);
assertUnknownVersion(PutIndexTemplateRequest.V_5_1_0);
assertUnknownVersion(QueryStringQueryBuilder.V_5_1_0_UNRELEASED);
assertUnknownVersion(SimpleQueryStringBuilder.V_5_1_0_UNRELEASED);
// once we released 5.0.0 and it's added to Version.java we need to remove this constant
assertUnknownVersion(Script.V_5_1_0_UNRELEASED);
// once we released 5.0.0 and it's added to Version.java we need to remove this constant

View File

@ -35,6 +35,7 @@ import org.elasticsearch.indices.InvalidIndexTemplateException;
import org.elasticsearch.test.ESSingleNodeTestCase;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -50,7 +51,7 @@ import static org.hamcrest.CoreMatchers.instanceOf;
public class MetaDataIndexTemplateServiceTests extends ESSingleNodeTestCase {
public void testIndexTemplateInvalidNumberOfShards() {
PutRequest request = new PutRequest("test", "test_shards");
request.template("test_shards*");
request.patterns(Collections.singletonList("test_shards*"));
Map<String, Object> map = new HashMap<>();
map.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, "0");
@ -69,7 +70,7 @@ public class MetaDataIndexTemplateServiceTests extends ESSingleNodeTestCase {
public void testIndexTemplateValidationAccumulatesValidationErrors() {
PutRequest request = new PutRequest("test", "putTemplate shards");
request.template("_test_shards*");
request.patterns(Collections.singletonList("_test_shards*"));
Map<String, Object> map = new HashMap<>();
map.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, "0");
@ -86,18 +87,18 @@ public class MetaDataIndexTemplateServiceTests extends ESSingleNodeTestCase {
public void testIndexTemplateWithAliasNameEqualToTemplatePattern() {
PutRequest request = new PutRequest("api", "foobar_template");
request.template("foobar");
request.patterns(Arrays.asList("foo", "foobar"));
request.aliases(Collections.singleton(new Alias("foobar")));
List<Throwable> errors = putTemplate(request);
assertThat(errors.size(), equalTo(1));
assertThat(errors.get(0), instanceOf(IllegalArgumentException.class));
assertThat(errors.get(0).getMessage(), equalTo("Alias [foobar] cannot be the same as the template pattern [foobar]"));
assertThat(errors.get(0).getMessage(), equalTo("Alias [foobar] cannot be the same as any pattern in [foo, foobar]"));
}
public void testIndexTemplateWithValidateEmptyMapping() throws Exception {
PutRequest request = new PutRequest("api", "validate_template");
request.template("validate_template");
request.patterns(Collections.singletonList("validate_template"));
request.putMapping("type1", "{}");
List<Throwable> errors = putTemplateDetail(request);
@ -108,7 +109,7 @@ public class MetaDataIndexTemplateServiceTests extends ESSingleNodeTestCase {
public void testIndexTemplateWithValidateMapping() throws Exception {
PutRequest request = new PutRequest("api", "validate_template");
request.template("te*");
request.patterns(Collections.singletonList("te*"));
request.putMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field2").field("type", "string").field("analyzer", "custom_1").endObject()
.endObject().endObject().endObject().string());
@ -121,7 +122,7 @@ public class MetaDataIndexTemplateServiceTests extends ESSingleNodeTestCase {
public void testBrokenMapping() throws Exception {
PutRequest request = new PutRequest("api", "broken_mapping");
request.template("te*");
request.patterns(Collections.singletonList("te*"));
request.putMapping("type1", "abcde");
List<Throwable> errors = putTemplateDetail(request);
@ -132,7 +133,7 @@ public class MetaDataIndexTemplateServiceTests extends ESSingleNodeTestCase {
public void testBlankMapping() throws Exception {
PutRequest request = new PutRequest("api", "blank_mapping");
request.template("te*");
request.patterns(Collections.singletonList("te*"));
request.putMapping("type1", "{}");
List<Throwable> errors = putTemplateDetail(request);
@ -144,7 +145,7 @@ public class MetaDataIndexTemplateServiceTests extends ESSingleNodeTestCase {
public void testAliasInvalidFilterInvalidJson() throws Exception {
//invalid json: put index template fails
PutRequest request = new PutRequest("api", "blank_mapping");
request.template("te*");
request.patterns(Collections.singletonList("te*"));
request.putMapping("type1", "{}");
Set<Alias> aliases = new HashSet<>();
aliases.add(new Alias("invalid_alias").filter("abcde"));

View File

@ -0,0 +1,69 @@
/*
* 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.action.admin.indices.template.put;
import org.elasticsearch.Version;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
public class PutIndexTemplateRequestTests extends ESTestCase {
// bwc for #21009
public void testPutIndexTemplateRequest510() throws IOException {
PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest("test");
putRequest.patterns(Collections.singletonList("test*"));
putRequest.order(5);
PutIndexTemplateRequest multiPatternRequest = new PutIndexTemplateRequest("test");
multiPatternRequest.patterns(Arrays.asList("test*", "*test2", "*test3*"));
multiPatternRequest.order(5);
// These bytes were retrieved by Base64 encoding the result of the above with 5_0_0 code.
// Note: Instead of a list for the template, in 5_0_0 the element was provided as a string.
String putRequestBytes = "ADwDAAR0ZXN0BXRlc3QqAAAABQAAAAAAAA==";
BytesArray bytes = new BytesArray(Base64.getDecoder().decode(putRequestBytes));
try (StreamInput in = bytes.streamInput()) {
in.setVersion(Version.V_5_0_0);
PutIndexTemplateRequest readRequest = new PutIndexTemplateRequest();
readRequest.readFrom(in);
assertEquals(putRequest.patterns(), readRequest.patterns());
assertEquals(putRequest.order(), readRequest.order());
BytesStreamOutput output = new BytesStreamOutput();
output.setVersion(Version.V_5_0_0);
readRequest.writeTo(output);
assertEquals(bytes.toBytesRef(), output.bytes().toBytesRef());
// test that multi templates are reverse-compatible.
// for the bwc case, if multiple patterns, use only the first pattern seen.
output.reset();
multiPatternRequest.writeTo(output);
assertEquals(bytes.toBytesRef(), output.bytes().toBytesRef());
}
}
}

View File

@ -46,6 +46,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.SortedSet;
@ -224,7 +225,7 @@ public class RestoreBackwardsCompatIT extends AbstractSnapshotIntegTestCase {
logger.info("--> check templates");
IndexTemplateMetaData template = clusterState.getMetaData().templates().get("template_" + version.toLowerCase(Locale.ROOT));
assertThat(template, notNullValue());
assertThat(template.template(), equalTo("te*"));
assertThat(template.patterns(), equalTo(Collections.singletonList("te*")));
assertThat(template.settings().getAsInt(IndexMetaData.SETTING_NUMBER_OF_SHARDS, -1), equalTo(1));
assertThat(template.mappings().size(), equalTo(1));
assertThat(template.mappings().get("type1").string(), equalTo("{\"type1\":{\"_source\":{\"enabled\":false}}}"));

View File

@ -553,7 +553,7 @@ public class ClusterStateDiffIT extends ESIntegTestCase {
public IndexTemplateMetaData randomCreate(String name) {
IndexTemplateMetaData.Builder builder = IndexTemplateMetaData.builder(name);
builder.order(randomInt(1000))
.template(randomName("temp"))
.patterns(Collections.singletonList(randomName("temp")))
.settings(randomSettings(Settings.EMPTY));
int aliasCount = randomIntBetween(0, 10);
for (int i = 0; i < aliasCount; i++) {

View File

@ -40,6 +40,8 @@ import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.hamcrest.CollectionAssertions;
import org.junit.Before;
import java.util.Collections;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertIndexTemplateExists;
import static org.hamcrest.Matchers.equalTo;
@ -92,7 +94,7 @@ public class SimpleClusterStateIT extends ESIntegTestCase {
public void testIndexTemplates() throws Exception {
client().admin().indices().preparePutTemplate("foo_template")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
@ -101,7 +103,7 @@ public class SimpleClusterStateIT extends ESIntegTestCase {
.get();
client().admin().indices().preparePutTemplate("fuu_template")
.setTemplate("test*")
.setPatterns(Collections.singletonList("test*"))
.setOrder(1)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field2").field("type", "text").field("store", "no").endObject()

View File

@ -20,7 +20,6 @@
package org.elasticsearch.cluster.metadata;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.common.xcontent.ToXContent;

View File

@ -0,0 +1,81 @@
/*
* 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.cluster.metadata;
import org.elasticsearch.Version;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collections;
import static org.elasticsearch.cluster.metadata.AliasMetaData.newAliasMetaDataBuilder;
public class IndexTemplateMetaDataTests extends ESTestCase {
// bwc for #21009
public void testIndexTemplateMetaData510() throws IOException {
IndexTemplateMetaData metaData = IndexTemplateMetaData.builder("foo")
.patterns(Collections.singletonList("bar"))
.order(1)
.settings(Settings.builder()
.put("setting1", "value1")
.put("setting2", "value2"))
.putAlias(newAliasMetaDataBuilder("alias-bar1")).build();
IndexTemplateMetaData multiMetaData = IndexTemplateMetaData.builder("foo")
.patterns(Arrays.asList("bar", "foo"))
.order(1)
.settings(Settings.builder()
.put("setting1", "value1")
.put("setting2", "value2"))
.putAlias(newAliasMetaDataBuilder("alias-bar1")).build();
// These bytes were retrieved by Base64 encoding the result of the above with 5_0_0 code
String templateBytes = "A2ZvbwAAAAEDYmFyAghzZXR0aW5nMQEGdmFsdWUxCHNldHRpbmcyAQZ2YWx1ZTIAAQphbGlhcy1iYXIxAAAAAAA=";
BytesArray bytes = new BytesArray(Base64.getDecoder().decode(templateBytes));
try (StreamInput in = bytes.streamInput()) {
in.setVersion(Version.V_5_0_0);
IndexTemplateMetaData readMetaData = IndexTemplateMetaData.Builder.readFrom(in);
assertEquals(0, in.available());
assertEquals(metaData.getName(), readMetaData.getName());
assertEquals(metaData.getPatterns(), readMetaData.getPatterns());
assertTrue(metaData.aliases().containsKey("alias-bar1"));
assertEquals(1, metaData.aliases().size());
BytesStreamOutput output = new BytesStreamOutput();
output.setVersion(Version.V_5_0_0);
readMetaData.writeTo(output);
assertEquals(bytes.toBytesRef(), output.bytes().toBytesRef());
// test that multi templates are reverse-compatible.
// for the bwc case, if multiple patterns, use only the first pattern seen.
output.reset();
multiMetaData.writeTo(output);
assertEquals(bytes.toBytesRef(), output.bytes().toBytesRef());
}
}
}

View File

@ -26,6 +26,7 @@ import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.util.Collections;
import static org.elasticsearch.cluster.metadata.AliasMetaData.newAliasMetaDataBuilder;
import static org.hamcrest.Matchers.equalTo;
@ -33,6 +34,7 @@ import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
public class ToAndFromJsonMetaDataTests extends ESTestCase {
public void testSimpleJsonFromAndTo() throws IOException {
MetaData metaData = MetaData.builder()
.put(IndexMetaData.builder("test1")
@ -113,7 +115,7 @@ public class ToAndFromJsonMetaDataTests extends ESTestCase {
.putAlias(newAliasMetaDataBuilder("alias2"))
.putAlias(newAliasMetaDataBuilder("alias4").filter(ALIAS_FILTER2)))
.put(IndexTemplateMetaData.builder("foo")
.template("bar")
.patterns(Collections.singletonList("bar"))
.order(1)
.settings(Settings.builder()
.put("setting1", "value1")
@ -134,7 +136,7 @@ public class ToAndFromJsonMetaDataTests extends ESTestCase {
.putAlias(newAliasMetaDataBuilder("alias2"))
.putAlias(newAliasMetaDataBuilder("alias4").filter(ALIAS_FILTER2)))
.put(IndexTemplateMetaData.builder("foo")
.template("bar")
.patterns(Collections.singletonList("bar"))
.order(1)
.settings(Settings.builder()
.put("setting1", "value1")
@ -292,7 +294,7 @@ public class ToAndFromJsonMetaDataTests extends ESTestCase {
// templates
assertThat(parsedMetaData.templates().get("foo").name(), is("foo"));
assertThat(parsedMetaData.templates().get("foo").template(), is("bar"));
assertThat(parsedMetaData.templates().get("foo").patterns(), is(Collections.singletonList("bar")));
assertThat(parsedMetaData.templates().get("foo").settings().get("index.setting1"), is("value1"));
assertThat(parsedMetaData.templates().get("foo").settings().getByPrefix("index.").get("setting2"), is("value2"));
assertThat(parsedMetaData.templates().get("foo").aliases().size(), equalTo(3));

View File

@ -53,6 +53,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;
@ -356,7 +357,7 @@ public class RecoveryFromGatewayIT extends ESIntegTestCase {
.setSource(jsonBuilder().startObject().startObject("type2").endObject().endObject())
.execute().actionGet();
client.admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
@ -383,7 +384,7 @@ public class RecoveryFromGatewayIT extends ESIntegTestCase {
ClusterState state = client().admin().cluster().prepareState().execute().actionGet().getState();
assertThat(state.metaData().index("test").mapping("type2"), notNullValue());
assertThat(state.metaData().templates().get("template_1").template(), equalTo("te*"));
assertThat(state.metaData().templates().get("template_1").patterns(), equalTo(Collections.singletonList("te*")));
assertThat(state.metaData().index("test").getAliases().get("test_alias"), notNullValue());
assertThat(state.metaData().index("test").getAliases().get("test_alias").filter(), notNullValue());
}

View File

@ -29,6 +29,7 @@ import org.elasticsearch.indices.TypeMissingException;
import org.elasticsearch.test.ESIntegTestCase;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicReference;
@ -129,7 +130,7 @@ public class DynamicMappingIT extends ESIntegTestCase {
public void testAutoCreateWithDisabledDynamicMappings() throws Exception {
assertAcked(client().admin().indices().preparePutTemplate("my_template")
.setCreate(true)
.setTemplate("index_*")
.setPatterns(Collections.singletonList("index_*"))
.addMapping("foo", "field", "type=keyword")
.setSettings(Settings.builder().put("index.mapper.dynamic", false).build())
.get());

View File

@ -26,6 +26,7 @@ import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
import java.io.IOException;
import java.util.Collections;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertBlocked;
import static org.hamcrest.Matchers.hasSize;
@ -35,7 +36,7 @@ public class IndexTemplateBlocksIT extends ESIntegTestCase {
public void testIndexTemplatesWithBlocks() throws IOException {
// creates a simple index template
client().admin().indices().preparePutTemplate("template_blocks")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
@ -50,7 +51,7 @@ public class IndexTemplateBlocksIT extends ESIntegTestCase {
assertThat(response.getIndexTemplates(), hasSize(1));
assertBlocked(client().admin().indices().preparePutTemplate("template_blocks_2")
.setTemplate("block*")
.setPatterns(Collections.singletonList("block*"))
.setOrder(0)
.addAlias(new Alias("alias_1")));

View File

@ -41,8 +41,10 @@ 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;
@ -80,7 +82,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
client().admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setSettings(indexSettings())
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
@ -90,7 +92,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
.get();
client().admin().indices().preparePutTemplate("template_2")
.setTemplate("test*")
.setPatterns(Collections.singletonList("test*"))
.setSettings(indexSettings())
.setOrder(1)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
@ -100,7 +102,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
// test create param
assertThrows(client().admin().indices().preparePutTemplate("template_2")
.setTemplate("test*")
.setPatterns(Collections.singletonList("test*"))
.setSettings(indexSettings())
.setCreate(true)
.setOrder(1)
@ -152,7 +154,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
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")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
@ -161,7 +163,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
.execute().actionGet();
client().admin().indices().preparePutTemplate("template_2")
.setTemplate("test*")
.setPatterns(Collections.singletonList("test*"))
.setOrder(1)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field2").field("type", "text").field("store", "no").endObject()
@ -180,7 +182,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
logger.info("--> put template_1 back");
client().admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
@ -202,7 +204,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
public void testThatGetIndexTemplatesWorks() throws Exception {
logger.info("--> put template_1");
client().admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.setVersion(123)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
@ -215,7 +217,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
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).getTemplate(), is("te*"));
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));
@ -228,7 +230,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
public void testThatGetIndexTemplatesWithSimpleRegexWorks() throws Exception {
logger.info("--> put template_1");
client().admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
@ -238,7 +240,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
logger.info("--> put template_2");
client().admin().indices().preparePutTemplate("template_2")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
@ -248,7 +250,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
logger.info("--> put template3");
client().admin().indices().preparePutTemplate("template3")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setOrder(0)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("field1").field("type", "text").field("store", true).endObject()
@ -316,7 +318,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
MapperParsingException e = expectThrows( MapperParsingException.class,
() -> client().admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.addMapping("type1", "abcde")
.get());
assertThat(e.getMessage(), containsString("Failed to parse mapping "));
@ -335,7 +337,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> client().admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.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" +
@ -353,7 +355,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
public void testIndexTemplateWithAliases() throws Exception {
client().admin().indices().preparePutTemplate("template_with_aliases")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.addMapping("type1", "{\"type1\" : {\"properties\" : {\"value\" : {\"type\" : \"text\"}}}}")
.addAlias(new Alias("simple_alias"))
.addAlias(new Alias("templated_alias-{index}"))
@ -440,7 +442,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
public void testIndexTemplateWithAliasesSource() {
client().admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setAliases(
" {\n" +
" \"alias1\" : {},\n" +
@ -478,7 +480,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
public void testDuplicateAlias() throws Exception {
client().admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.addAlias(new Alias("my_alias").filter(termQuery("field", "value1")))
.addAlias(new Alias("my_alias").filter(termQuery("field", "value2")))
.get();
@ -492,7 +494,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
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")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.addAlias(new Alias("invalid_alias").filter("{ \"invalid\": {} }")).get();
GetIndexTemplatesResponse response = client().admin().indices().prepareGetTemplates("template_1").get();
@ -510,7 +512,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
public void testAliasInvalidFilterInvalidJson() throws Exception {
//invalid json: put index template fails
PutIndexTemplateRequestBuilder putIndexTemplateRequestBuilder = client().admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.addAlias(new Alias("invalid_alias").filter("abcde"));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
@ -525,7 +527,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
createIndex("index");
client().admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.addAlias(new Alias("index")).get();
InvalidAliasNameException e = expectThrows(InvalidAliasNameException.class,
@ -535,7 +537,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
public void testAliasEmptyName() throws Exception {
PutIndexTemplateRequestBuilder putIndexTemplateRequestBuilder = client().admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.addAlias(new Alias(" ").indexRouting("1,2,3"));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
@ -545,7 +547,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
public void testAliasWithMultipleIndexRoutings() throws Exception {
PutIndexTemplateRequestBuilder putIndexTemplateRequestBuilder = client().admin().indices().preparePutTemplate("template_1")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.addAlias(new Alias("alias").indexRouting("1,2,3"));
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
@ -555,7 +557,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
public void testMultipleAliasesPrecedence() throws Exception {
client().admin().indices().preparePutTemplate("template1")
.setTemplate("*")
.setPatterns(Collections.singletonList("*"))
.setOrder(0)
.addAlias(new Alias("alias1"))
.addAlias(new Alias("{index}-alias"))
@ -563,7 +565,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
.addAlias(new Alias("alias4")).get();
client().admin().indices().preparePutTemplate("template2")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setOrder(1)
.addAlias(new Alias("alias1").routing("test"))
.addAlias(new Alias("alias3")).get();
@ -593,27 +595,27 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
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")
.setTemplate("a*")
.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")
.setTemplate("b*")
.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")
.setTemplate("c*")
.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")
.setTemplate("d*")
.setPatterns(Collections.singletonList("d*"))
.setOrder(0)
.addAlias(new Alias("alias4").filter(termQuery("field", "value"))).get();
@ -672,7 +674,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
//Now, a complete mapping with two separated templates is error
// base template
client().admin().indices().preparePutTemplate("template_1")
.setTemplate("*")
.setPatterns(Collections.singletonList("*"))
.setSettings(
" {\n" +
" \"index\" : {\n" +
@ -690,7 +692,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
// put template using custom_1 analyzer
MapperParsingException e = expectThrows(MapperParsingException.class,
() -> client().admin().indices().preparePutTemplate("template_2")
.setTemplate("test*")
.setPatterns(Collections.singletonList("test*"))
.setCreate(true)
.setOrder(1)
.addMapping("type1", XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
@ -709,7 +711,7 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
Integer version = randomBoolean() ? randomInt() : null;
assertAcked(client().admin().indices().preparePutTemplate("versioned_template")
.setTemplate("te*")
.setPatterns(Collections.singletonList("te*"))
.setVersion(version)
.setOrder(order)
.addMapping("test", "field", "type=text")
@ -721,4 +723,46 @@ public class SimpleIndexTemplateIT extends ESIntegTestCase {
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").value().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").value().toString());
assertNull(searchResponse.getHits().getAt(0).field("field2"));
}
}

View File

@ -445,7 +445,7 @@ public class SharedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTestCas
.setType("fs").setSettings(Settings.builder().put("location", randomRepoPath())));
logger.info("--> creating test template");
assertThat(client.admin().indices().preparePutTemplate("test-template").setTemplate("te*").addMapping("test-mapping", XContentFactory.jsonBuilder().startObject().startObject("test-mapping").startObject("properties")
assertThat(client.admin().indices().preparePutTemplate("test-template").setPatterns(Collections.singletonList("te*")).addMapping("test-mapping", XContentFactory.jsonBuilder().startObject().startObject("test-mapping").startObject("properties")
.startObject("field1").field("type", "string").field("store", "yes").endObject()
.startObject("field2").field("type", "string").field("store", "yes").field("index", "not_analyzed").endObject()
.endObject().endObject().endObject()).get().isAcknowledged(), equalTo(true));
@ -486,7 +486,7 @@ public class SharedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTestCas
if(testTemplate) {
logger.info("--> creating test template");
assertThat(client.admin().indices().preparePutTemplate("test-template").setTemplate("te*").addMapping("test-mapping", XContentFactory.jsonBuilder().startObject().startObject("test-mapping").startObject("properties")
assertThat(client.admin().indices().preparePutTemplate("test-template").setPatterns(Collections.singletonList("te*")).addMapping("test-mapping", XContentFactory.jsonBuilder().startObject().startObject("test-mapping").startObject("properties")
.startObject("field1").field("type", "string").field("store", "yes").endObject()
.startObject("field2").field("type", "string").field("store", "yes").field("index", "not_analyzed").endObject()
.endObject().endObject().endObject()).get().isAcknowledged(), equalTo(true));

View File

@ -191,7 +191,7 @@ order by column3.
[source,sh]
--------------------------------------------------
GET _cat/templates?v&s=order:desc,template
GET _cat/templates?v&s=order:desc,index_patterns
--------------------------------------------------
//CONSOLE
@ -199,10 +199,10 @@ returns:
[source,sh]
--------------------------------------------------
name template order version
pizza_pepperoni *pepperoni* 2
sushi_california_roll *avocado* 1 1
pizza_hawaiian *pineapples* 1
name index_patterns order version
pizza_pepperoni [*pepperoni*] 2
sushi_california_roll [*avocado*] 1 1
pizza_hawaiian [*pineapples*] 1
--------------------------------------------------
--

View File

@ -3,8 +3,8 @@
Index templates allow you to define templates that will automatically be
applied when new indices are created. The templates include both settings and
mappings, and a simple pattern template that controls whether the template
should be applied to the new index.
mappings, and a list of patterns that control whether the template should be
applied to the new index.
NOTE: Templates are only applied at index creation time. Changing a template
will have no impact on existing indices.
@ -15,7 +15,7 @@ For example:
--------------------------------------------------
PUT _template/template_1
{
"template": "te*",
"index_patterns": ["te*", "bar*"],
"settings": {
"number_of_shards": 1
},
@ -53,7 +53,7 @@ It is also possible to include aliases in an index template as follows:
--------------------------------------------------
PUT _template/template_1
{
"template" : "te*",
"index_patterns" : ["te*"],
"settings" : {
"number_of_shards" : 1
},
@ -147,7 +147,7 @@ orders overriding them. For example:
--------------------------------------------------
PUT /_template/template_1
{
"template" : "*",
"index_patterns" : ["*"],
"order" : 0,
"settings" : {
"number_of_shards" : 1
@ -161,7 +161,7 @@ PUT /_template/template_1
PUT /_template/template_2
{
"template" : "te*",
"index_patterns" : ["te*"],
"order" : 1,
"settings" : {
"number_of_shards" : 1
@ -196,7 +196,7 @@ one.
--------------------------------------------------
PUT /_template/template_1
{
"template" : "*",
"index_patterns" : ["*"],
"order" : 0,
"settings" : {
"number_of_shards" : 1

View File

@ -61,7 +61,7 @@ Automatic type creation can also be disabled for all indices by setting an index
--------------------------------------------------
PUT _template/template_all
{
"template": "*",
"index_patterns": ["*"],
"order":0,
"settings": {
"index.mapper.dynamic": false <1>

View File

@ -44,7 +44,7 @@ within automatically created indices:
--------------------------------------------------
PUT _template/logging
{
"template": "logs-*", <1>
"index_patterns": ["logs-*"], <1>
"settings": { "number_of_shards": 1 }, <2>
"mappings": {
"_default_": {

View File

@ -407,7 +407,7 @@ new indices, you could create the following index template:
PUT _template/disable_all_field
{
"order": 0,
"template": "*", <1>
"index_patterns": ["*"], <1>
"mappings": {
"_default_": { <2>
"_all": { <3>

View File

@ -10,7 +10,7 @@
- match:
$body: |
/^ name .+ \n
template .+ \n
index_patterns .+ \n
order .+ \n
version .+ \n
$/
@ -39,7 +39,7 @@
body:
order: 0
version: 1
template: test-*
index_patterns: test-*
settings:
number_of_shards: 1
number_of_replicas: 0
@ -50,7 +50,7 @@
body:
order: 1
version: 2
template: test-2*
index_patterns: test-2*
settings:
number_of_shards: 1
number_of_replicas: 0
@ -61,7 +61,7 @@
- match:
$body: /
(^|\n)test \s+
test-\* \s+
\[test-\*\] \s+
0 \s+
1
(\n|$)
@ -70,7 +70,7 @@
- match:
$body: /
(^|\n)test_2 \s+
test-2\* \s+
\[test-2\*\] \s+
1 \s+
2
(\n|$)
@ -87,7 +87,7 @@
body:
order: 0
version: 1
template: t*
index_patterns: t*
settings:
number_of_shards: 1
number_of_replicas: 0
@ -98,7 +98,7 @@
body:
order: 2
version: 1
template: tea*
index_patterns: tea*
settings:
number_of_shards: 1
number_of_replicas: 0
@ -111,7 +111,7 @@
$body: |
/^
test \s+
t\* \s+
\[t\*\] \s+
0 \s+
1
\n
@ -128,7 +128,7 @@
body:
order: 0
version: 1
template: t*
index_patterns: t*
settings:
number_of_shards: 1
number_of_replicas: 0
@ -142,12 +142,12 @@
$body: |
/^
name \s+
template \s+
index_patterns \s+
order \s+
version
\n
test \s+
t\* \s+
\[t\*\] \s+
0 \s+
1
\n
@ -164,14 +164,14 @@
body:
order: 0
version: 1
template: t*
index_patterns: t*
settings:
number_of_shards: 1
number_of_replicas: 0
- do:
cat.templates:
h: [name, template]
h: [name, index_patterns]
v: true
name: test*
@ -179,10 +179,10 @@
$body: |
/^
name \s+
template
index_patterns
\n
test \s+
t\*
\[t\*\]
\n
$/
@ -196,7 +196,7 @@
name: test
body:
order: 0
template: t*
index_patterns: t*
settings:
number_of_shards: 1
number_of_replicas: 0
@ -207,31 +207,62 @@
body:
order: 0
version: 1
template: te*
index_patterns: te*
settings:
number_of_shards: 1
number_of_replicas: 0
- do:
cat.templates:
h: [name, template, version]
h: [name, index_patterns, version]
s: [version]
- match:
$body: |
/^
test \s+ t\* \s+\n
test_1 \s+ te\* \s+ 1\n
test \s+ \[t\*\] \s+ \n
test_1 \s+ \[te\*\] \s+ 1 \n
$/
- do:
cat.templates:
h: [name, template, version]
h: [name, index_patterns, version]
s: ["version:desc"]
- match:
$body: |
/^
test_1 \s+ te\* \s+ 1\n
test \s+ t\* \s+\n
test_1 \s+ \[te\*\] \s+ 1\n
test \s+ \[t\*\] \s+ \n
$/
---
"Multiple template":
- do:
indices.put_template:
name: test_1
body:
order: 0
version: 1
index_patterns: [t*, te*]
settings:
number_of_shards: 1
number_of_replicas: 0
- do:
cat.templates:
h: [name, index_patterns]
v: true
- match:
$body: |
/^
name \s+
index_patterns
\n
test_1 \s+
\[t\*,\ te\*\]
\n
$/

View File

@ -16,7 +16,7 @@ setup:
indices.put_template:
name: test
body:
template: 'test-*'
index_patterns: ['test-*']
settings:
number_of_shards: 1
number_of_replicas: 0

View File

@ -3,7 +3,7 @@ setup:
indices.put_template:
name: test
body:
template: test-*
index_patterns: test-*
settings:
number_of_shards: 1
number_of_replicas: 0
@ -15,7 +15,7 @@ setup:
indices.get_template:
name: test
- match: {test.template: "test-*"}
- match: {test.index_patterns: ["test-*"]}
- match: {test.settings: {index: {number_of_shards: '1', number_of_replicas: '0'}}}
---
@ -25,15 +25,15 @@ setup:
indices.put_template:
name: test2
body:
template: test2-*
index_patterns: test2-*
settings:
number_of_shards: 1
- do:
indices.get_template: {}
- match: {test.template: "test-*"}
- match: {test2.template: "test2-*"}
- match: {test.index_patterns: ["test-*"]}
- match: {test2.index_patterns: ["test2-*"]}
---
"Get template with local flag":

View File

@ -4,7 +4,7 @@
indices.put_template:
name: test
body:
template: test-*
index_patterns: test-*
settings:
number_of_shards: 1
number_of_replicas: 0
@ -14,7 +14,26 @@
name: test
flat_settings: true
- match: {test.template: "test-*"}
- match: {test.index_patterns: ["test-*"]}
- match: {test.settings: {index.number_of_shards: '1', index.number_of_replicas: '0'}}
---
"Put multiple template":
- do:
indices.put_template:
name: test
body:
index_patterns: [test-*, test2-*]
settings:
number_of_shards: 1
number_of_replicas: 0
- do:
indices.get_template:
name: test
flat_settings: true
- match: {test.index_patterns: ["test-*", "test2-*"]}
- match: {test.settings: {index.number_of_shards: '1', index.number_of_replicas: '0'}}
---
@ -23,7 +42,7 @@
indices.put_template:
name: test
body:
template: test-*
index_patterns: test-*
aliases:
test_alias: {}
test_blias: { routing: b }
@ -33,7 +52,7 @@
indices.get_template:
name: test
- match: { test.template: "test-*" }
- match: { test.index_patterns: ["test-*"] }
- length: { test.aliases: 3 }
- is_true: test.aliases.test_alias
- match: { test.aliases.test_blias.index_routing: "b" }
@ -47,7 +66,7 @@
name: test
create: true
body:
template: test-*
index_patterns: test-*
settings:
number_of_shards: 1
number_of_replicas: 0
@ -57,7 +76,7 @@
name: test
flat_settings: true
- match: {test.template: "test-*"}
- match: {test.index_patterns: ["test-*"]}
- match: {test.settings: {index.number_of_shards: '1', index.number_of_replicas: '0'}}
- do:
@ -66,7 +85,7 @@
name: test
create: true
body:
template: test-*
index_patterns: test-*
settings:
number_of_shards: 1
number_of_replicas: 0
@ -79,7 +98,7 @@
body: >
{
"version": 10,
"template": "*",
"index_patterns": "*",
"settings": { "number_of_shards": 1 }
}
- match: { acknowledged: true }
@ -96,7 +115,7 @@
body: >
{
"version": 9,
"template": "*",
"index_patterns": "*",
"settings": { "number_of_shards": 1 }
}
- match: { acknowledged: true }
@ -113,7 +132,7 @@
body: >
{
"version": 6789,
"template": "*",
"index_patterns": "*",
"settings": { "number_of_shards": 1 }
}
- match: { acknowledged: true }
@ -129,7 +148,7 @@
name: "my_template"
body: >
{
"template": "*",
"index_patterns": "*",
"settings": { "number_of_shards": 1 }
}
- match: { acknowledged: true }
@ -146,7 +165,7 @@
body: >
{
"version": 5385,
"template": "*",
"index_patterns": "*",
"settings": { "number_of_shards": 1 }
}
- match: { acknowledged: true }

View File

@ -408,7 +408,7 @@ public abstract class ESIntegTestCase extends ESTestCase {
}
PutIndexTemplateRequestBuilder putTemplate = client().admin().indices()
.preparePutTemplate("random_index_template")
.setTemplate("*")
.setPatterns(Collections.singletonList("*"))
.setOrder(0)
.setSettings(randomSettingsBuilder);
if (mappings != null) {

View File

@ -87,7 +87,7 @@ public abstract class ESSingleNodeTestCase extends ESTestCase {
assertFalse(clusterHealthResponse.isTimedOut());
client().admin().indices()
.preparePutTemplate("random_index_template")
.setTemplate("*")
.setPatterns(Collections.singletonList("*"))
.setOrder(0)
.setSettings(Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)).get();