Index Templates: Allow to place them under config/templates, closes #1703.

This commit is contained in:
Shay Banon 2012-02-15 11:45:58 +02:00
parent fe11368c89
commit 103f587be1
5 changed files with 67 additions and 17 deletions

View File

@ -468,15 +468,13 @@ public class IndexMetaData {
}
builder.settings(settingsBuilder.build());
} else if ("mappings".equals(currentFieldName)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
if (token == XContentParser.Token.VALUE_EMBEDDED_OBJECT) {
builder.putMapping(new MappingMetaData(new CompressedString(parser.binaryValue())));
} else {
Map<String, Object> mapping = parser.mapOrdered();
if (mapping.size() == 1) {
String mappingType = mapping.keySet().iterator().next();
builder.putMapping(new MappingMetaData(mappingType, mapping));
}
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
String mappingType = currentFieldName;
Map<String, Object> mappingSource = MapBuilder.<String, Object>newMapBuilder().put(mappingType, parser.mapOrdered()).map();
builder.putMapping(new MappingMetaData(mappingType, mappingSource));
}
}
} else if ("aliases".equals(currentFieldName)) {

View File

@ -47,6 +47,7 @@ public class IndexTemplateMetaData {
private final Settings settings;
// the mapping source should always include the type as top level
private final ImmutableMap<String, CompressedString> mappings;
public IndexTemplateMetaData(String name, int order, String template, Settings settings, ImmutableMap<String, CompressedString> mappings) {
@ -210,8 +211,7 @@ public class IndexTemplateMetaData {
for (Map.Entry<String, CompressedString> entry : indexTemplateMetaData.mappings().entrySet()) {
byte[] data = entry.getValue().uncompressed();
XContentParser parser = XContentFactory.xContent(data).createParser(data);
Map<String, Object> mapping = parser.map();
parser.close();
Map<String, Object> mapping = parser.mapOrderedAndClose();
builder.map(mapping);
}
builder.endArray();
@ -219,6 +219,21 @@ public class IndexTemplateMetaData {
builder.endObject();
}
public static IndexTemplateMetaData fromXContentStandalone(XContentParser parser) throws IOException {
XContentParser.Token token = parser.nextToken();
if (token == null) {
throw new IOException("no data");
}
if (token != XContentParser.Token.START_OBJECT) {
throw new IOException("should start object");
}
token = parser.nextToken();
if (token != XContentParser.Token.FIELD_NAME) {
throw new IOException("the first field should be the template name");
}
return fromXContent(parser);
}
public static IndexTemplateMetaData fromXContent(XContentParser parser) throws IOException {
Builder builder = new Builder(parser.currentName());
@ -238,8 +253,20 @@ public class IndexTemplateMetaData {
}
builder.settings(settingsBuilder.build());
} else if ("mappings".equals(currentFieldName)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if (token == XContentParser.Token.START_OBJECT) {
String mappingType = currentFieldName;
Map<String, Object> mappingSource = MapBuilder.<String, Object>newMapBuilder().put(mappingType, parser.mapOrdered()).map();
builder.putMapping(mappingType, XContentFactory.jsonBuilder().map(mappingSource).string());
}
}
}
} else if (token == XContentParser.Token.START_ARRAY) {
if ("mappings".equals(currentFieldName)) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
Map<String, Object> mapping = parser.map();
Map<String, Object> mapping = parser.mapOrdered();
if (mapping.size() == 1) {
String mappingType = mapping.keySet().iterator().next();
String mappingSource = XContentFactory.jsonBuilder().map(mapping).string();

View File

@ -19,10 +19,10 @@
package org.elasticsearch.cluster.metadata;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.io.Closeables;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.ClusterService;
@ -46,6 +46,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.env.Environment;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.mapper.DocumentMapper;
@ -141,10 +142,9 @@ public class MetaDataCreateIndexService extends AbstractComponent {
return currentState;
}
List<IndexTemplateMetaData> templates = ImmutableList.of();
// we only find a template when its an API call (a new index)
// find templates, highest order are better matching
templates = findTemplates(request, currentState);
List<IndexTemplateMetaData> templates = findTemplates(request, currentState);
// add the request mapping
Map<String, Map<String, Object>> mappings = Maps.newHashMap();
@ -398,6 +398,30 @@ public class MetaDataCreateIndexService extends AbstractComponent {
templates.add(template);
}
}
// see if we have templates defined under config
File templatesDir = new File(environment.configFile(), "templates");
if (templatesDir.exists() && templatesDir.isDirectory()) {
File[] templatesFiles = templatesDir.listFiles();
if (templatesFiles != null) {
for (File templatesFile : templatesFiles) {
XContentParser parser = null;
try {
byte[] templatesData = Streams.copyToByteArray(templatesFile);
parser = XContentHelper.createParser(templatesData, 0, templatesData.length);
IndexTemplateMetaData template = IndexTemplateMetaData.Builder.fromXContentStandalone(parser);
if (Regex.simpleMatch(template.template(), request.index)) {
templates.add(template);
}
} catch (Exception e) {
logger.warn("[{}] failed to read template [{}] from config", request.index, templatesFile.getAbsolutePath());
} finally {
Closeables.closeQuietly(parser);
}
}
}
}
Collections.sort(templates, new Comparator<IndexTemplateMetaData>() {
@Override
public int compare(IndexTemplateMetaData o1, IndexTemplateMetaData o2) {

View File

@ -19,13 +19,14 @@
package org.elasticsearch.common.xcontent;
import java.io.Closeable;
import java.io.IOException;
import java.util.Map;
/**
*
*/
public interface XContentParser {
public interface XContentParser extends Closeable {
enum Token {
START_OBJECT {

View File

@ -71,7 +71,7 @@ public class RestPutIndexTemplateAction extends BaseRestHandler {
// parse the parameters
Map<String, Object> source = XContentFactory.xContent(request.contentByteArray(), request.contentByteArrayOffset(), request.contentLength())
.createParser(request.contentByteArray(), request.contentByteArrayOffset(), request.contentLength()).mapAndClose();
.createParser(request.contentByteArray(), request.contentByteArrayOffset(), request.contentLength()).mapOrderedAndClose();
if (source.containsKey("template")) {
putRequest.template(source.get("template").toString());