remove Ingest's Internal Template Service (#25085)

Ingest was using it's own wrapper around TemplateScripts and the ScriptService.
This commit removes that abstraction
This commit is contained in:
Tal Levy 2017-06-08 15:24:03 -07:00 committed by GitHub
parent 119f8ed9f0
commit 340909582f
27 changed files with 192 additions and 300 deletions

View File

@ -22,6 +22,10 @@ package org.elasticsearch.ingest;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.ExceptionsHelper;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.script.TemplateScript;
import java.util.ArrayList;
import java.util.Arrays;
@ -29,6 +33,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.script.Script.DEFAULT_TEMPLATE_LANG;
public final class ConfigurationUtils {
public static final String TAG_KEY = "tag";
@ -265,10 +271,24 @@ public final class ConfigurationUtils {
return processors;
}
public static TemplateService.Template compileTemplate(String processorType, String processorTag, String propertyName,
String propertyValue, TemplateService templateService) {
public static TemplateScript.Factory compileTemplate(String processorType, String processorTag, String propertyName,
String propertyValue, ScriptService scriptService) {
try {
return templateService.compile(propertyValue);
// This check is here because the DEFAULT_TEMPLATE_LANG(mustache) is not
// installed for use by REST tests. `propertyValue` will not be
// modified if templating is not available so a script that simply returns an unmodified `propertyValue`
// is returned.
if (scriptService.isLangSupported(DEFAULT_TEMPLATE_LANG)) {
Script script = new Script(ScriptType.INLINE, DEFAULT_TEMPLATE_LANG, propertyValue, Collections.emptyMap());
return scriptService.compile(script, TemplateScript.CONTEXT);
} else {
return (params) -> new TemplateScript(params) {
@Override
public String execute() {
return propertyValue;
}
};
}
} catch (Exception e) {
throw ConfigurationUtils.newConfigurationException(processorType, processorTag, propertyName, e);
}

View File

@ -27,6 +27,8 @@ import org.elasticsearch.index.mapper.ParentFieldMapper;
import org.elasticsearch.index.mapper.RoutingFieldMapper;
import org.elasticsearch.index.mapper.SourceFieldMapper;
import org.elasticsearch.index.mapper.TypeFieldMapper;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.TemplateScript;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
@ -144,7 +146,7 @@ public final class IngestDocument {
* @throws IllegalArgumentException if the pathTemplate is null, empty, invalid, if the field doesn't exist,
* or if the field that is found at the provided path is not of the expected type.
*/
public <T> T getFieldValue(TemplateService.Template pathTemplate, Class<T> clazz) {
public <T> T getFieldValue(TemplateScript.Factory pathTemplate, Class<T> clazz) {
return getFieldValue(renderTemplate(pathTemplate), clazz);
}
@ -191,7 +193,7 @@ public final class IngestDocument {
* @return true if the document contains a value for the field, false otherwise
* @throws IllegalArgumentException if the path is null, empty or invalid
*/
public boolean hasField(TemplateService.Template fieldPathTemplate) {
public boolean hasField(TemplateScript.Factory fieldPathTemplate) {
return hasField(renderTemplate(fieldPathTemplate));
}
@ -280,7 +282,7 @@ public final class IngestDocument {
* @param fieldPathTemplate Resolves to the path with dot-notation within the document
* @throws IllegalArgumentException if the path is null, empty, invalid or if the field doesn't exist.
*/
public void removeField(TemplateService.Template fieldPathTemplate) {
public void removeField(TemplateScript.Factory fieldPathTemplate) {
removeField(renderTemplate(fieldPathTemplate));
}
@ -391,9 +393,9 @@ public final class IngestDocument {
* @param valueSource The value source that will produce the value or values to append to the existing ones
* @throws IllegalArgumentException if the path is null, empty or invalid.
*/
public void appendFieldValue(TemplateService.Template fieldPathTemplate, ValueSource valueSource) {
public void appendFieldValue(TemplateScript.Factory fieldPathTemplate, ValueSource valueSource) {
Map<String, Object> model = createTemplateModel();
appendFieldValue(fieldPathTemplate.execute(model), valueSource.copyAndResolve(model));
appendFieldValue(fieldPathTemplate.newInstance(model).execute(), valueSource.copyAndResolve(model));
}
/**
@ -419,9 +421,9 @@ public final class IngestDocument {
* @throws IllegalArgumentException if the path is null, empty, invalid or if the value cannot be set to the
* item identified by the provided path.
*/
public void setFieldValue(TemplateService.Template fieldPathTemplate, ValueSource valueSource) {
public void setFieldValue(TemplateScript.Factory fieldPathTemplate, ValueSource valueSource) {
Map<String, Object> model = createTemplateModel();
setFieldValue(fieldPathTemplate.execute(model), valueSource.copyAndResolve(model), false);
setFieldValue(fieldPathTemplate.newInstance(model).execute(), valueSource.copyAndResolve(model), false);
}
private void setFieldValue(String path, Object value, boolean append) {
@ -549,8 +551,8 @@ public final class IngestDocument {
clazz.getName() + "]");
}
public String renderTemplate(TemplateService.Template template) {
return template.execute(createTemplateModel());
public String renderTemplate(TemplateScript.Factory template) {
return template.newInstance(createTemplateModel()).execute();
}
private Map<String, Object> createTemplateModel() {

View File

@ -49,9 +49,7 @@ public class IngestService {
public IngestService(ClusterSettings clusterSettings, Settings settings, ThreadPool threadPool,
Environment env, ScriptService scriptService, AnalysisRegistry analysisRegistry,
List<IngestPlugin> ingestPlugins) {
final TemplateService templateService = new InternalTemplateService(scriptService);
Processor.Parameters parameters = new Processor.Parameters(env, scriptService, templateService,
Processor.Parameters parameters = new Processor.Parameters(env, scriptService,
analysisRegistry, threadPool.getThreadContext());
Map<String, Processor.Factory> processorFactories = new HashMap<>();
for (IngestPlugin ingestPlugin : ingestPlugins) {

View File

@ -1,79 +0,0 @@
/*
* 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.ingest;
import java.util.Collections;
import java.util.Map;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.script.TemplateScript;
public class InternalTemplateService implements TemplateService {
private final ScriptService scriptService;
InternalTemplateService(ScriptService scriptService) {
this.scriptService = scriptService;
}
@Override
public Template compile(String template) {
int mustacheStart = template.indexOf("{{");
int mustacheEnd = template.indexOf("}}");
if (mustacheStart != -1 && mustacheEnd != -1 && mustacheStart < mustacheEnd) {
Script script = new Script(ScriptType.INLINE, "mustache", template, Collections.emptyMap());
TemplateScript.Factory compiledTemplate = scriptService.compile(script, TemplateScript.CONTEXT);
return new Template() {
@Override
public String execute(Map<String, Object> model) {
return compiledTemplate.newInstance(model).execute();
}
@Override
public String getKey() {
return template;
}
};
} else {
return new StringTemplate(template);
}
}
class StringTemplate implements Template {
private final String value;
StringTemplate(String value) {
this.value = value;
}
@Override
public String execute(Map<String, Object> model) {
return value;
}
@Override
public String getKey() {
return value;
}
}
}

View File

@ -84,11 +84,6 @@ public interface Processor {
*/
public final ScriptService scriptService;
/**
* Provides template support to pipeline settings.
*/
public final TemplateService templateService;
/**
* Provide analyzer support
*/
@ -100,11 +95,10 @@ public interface Processor {
*/
public final ThreadContext threadContext;
public Parameters(Environment env, ScriptService scriptService, TemplateService templateService,
public Parameters(Environment env, ScriptService scriptService,
AnalysisRegistry analysisRegistry, ThreadContext threadContext) {
this.env = env;
this.scriptService = scriptService;
this.templateService = templateService;
this.threadContext = threadContext;
this.analysisRegistry = analysisRegistry;
}

View File

@ -1,38 +0,0 @@
/*
* 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.ingest;
import java.util.Map;
/**
* Abstraction for the ingest template engine used to decouple {@link IngestDocument} from {@link org.elasticsearch.script.ScriptService}.
* Allows to compile a template into an ingest {@link Template} object.
* A compiled template can be executed by calling its {@link Template#execute(Map)} method.
*/
public interface TemplateService {
Template compile(String template);
interface Template {
String execute(Map<String, Object> model);
String getKey();
}
}

View File

@ -19,13 +19,21 @@
package org.elasticsearch.ingest;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.script.TemplateScript;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static org.elasticsearch.script.Script.DEFAULT_TEMPLATE_LANG;
/**
* Holds a value. If the value is requested a copy is made and optionally template snippets are resolved too.
*/
@ -41,13 +49,14 @@ public interface ValueSource {
*/
Object copyAndResolve(Map<String, Object> model);
static ValueSource wrap(Object value, TemplateService templateService) {
static ValueSource wrap(Object value, ScriptService scriptService) {
if (value instanceof Map) {
@SuppressWarnings("unchecked")
Map<Object, Object> mapValue = (Map) value;
Map<ValueSource, ValueSource> valueTypeMap = new HashMap<>(mapValue.size());
for (Map.Entry<Object, Object> entry : mapValue.entrySet()) {
valueTypeMap.put(wrap(entry.getKey(), templateService), wrap(entry.getValue(), templateService));
valueTypeMap.put(wrap(entry.getKey(), scriptService), wrap(entry.getValue(), scriptService));
}
return new MapValue(valueTypeMap);
} else if (value instanceof List) {
@ -55,7 +64,7 @@ public interface ValueSource {
List<Object> listValue = (List) value;
List<ValueSource> valueSourceList = new ArrayList<>(listValue.size());
for (Object item : listValue) {
valueSourceList.add(wrap(item, templateService));
valueSourceList.add(wrap(item, scriptService));
}
return new ListValue(valueSourceList);
} else if (value == null || value instanceof Number || value instanceof Boolean) {
@ -63,7 +72,15 @@ public interface ValueSource {
} else if (value instanceof byte[]) {
return new ByteValue((byte[]) value);
} else if (value instanceof String) {
return new TemplatedValue(templateService.compile((String) value));
// This check is here because the DEFAULT_TEMPLATE_LANG(mustache) is not
// installed for use by REST tests. `value` will not be
// modified if templating is not available
if (scriptService.isLangSupported(DEFAULT_TEMPLATE_LANG)) {
Script script = new Script(ScriptType.INLINE, DEFAULT_TEMPLATE_LANG, (String) value, Collections.emptyMap());
return new TemplatedValue(scriptService.compile(script, TemplateScript.CONTEXT));
} else {
return new ObjectValue(value);
}
} else {
throw new IllegalArgumentException("unexpected value type [" + value.getClass() + "]");
}
@ -194,15 +211,15 @@ public interface ValueSource {
final class TemplatedValue implements ValueSource {
private final TemplateService.Template template;
private final TemplateScript.Factory template;
TemplatedValue(TemplateService.Template template) {
TemplatedValue(TemplateScript.Factory template) {
this.template = template;
}
@Override
public Object copyAndResolve(Map<String, Object> model) {
return template.execute(model);
return template.newInstance(model).execute();
}
@Override
@ -211,12 +228,12 @@ public interface ValueSource {
if (o == null || getClass() != o.getClass()) return false;
TemplatedValue templatedValue = (TemplatedValue) o;
return Objects.equals(template.getKey(), templatedValue.template.getKey());
return Objects.equals(template, templatedValue.template);
}
@Override
public int hashCode() {
return Objects.hashCode(template.getKey());
return Objects.hashCode(template);
}
}

View File

@ -49,7 +49,7 @@ public class ValueSourceTests extends ESTestCase {
myPreciousMap.put("field2", "value2");
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
ingestDocument.setFieldValue(TestTemplateService.instance().compile("field1"),
ingestDocument.setFieldValue(new TestTemplateService.MockTemplateScript.Factory("field1"),
ValueSource.wrap(myPreciousMap, TestTemplateService.instance()));
ingestDocument.removeField("field1.field2");
@ -62,7 +62,7 @@ public class ValueSourceTests extends ESTestCase {
myPreciousList.add("value");
IngestDocument ingestDocument = new IngestDocument(new HashMap<>(), new HashMap<>());
ingestDocument.setFieldValue(TestTemplateService.instance().compile("field1"),
ingestDocument.setFieldValue(new TestTemplateService.MockTemplateScript.Factory("field1"),
ValueSource.wrap(myPreciousList, TestTemplateService.instance()));
ingestDocument.removeField("field1.0");

View File

@ -23,8 +23,9 @@ import org.elasticsearch.ingest.AbstractProcessor;
import org.elasticsearch.ingest.ConfigurationUtils;
import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.ingest.Processor;
import org.elasticsearch.ingest.TemplateService;
import org.elasticsearch.ingest.ValueSource;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.TemplateScript;
import java.util.Map;
@ -37,16 +38,16 @@ public final class AppendProcessor extends AbstractProcessor {
public static final String TYPE = "append";
private final TemplateService.Template field;
private final TemplateScript.Factory field;
private final ValueSource value;
AppendProcessor(String tag, TemplateService.Template field, ValueSource value) {
AppendProcessor(String tag, TemplateScript.Factory field, ValueSource value) {
super(tag);
this.field = field;
this.value = value;
}
public TemplateService.Template getField() {
public TemplateScript.Factory getField() {
return field;
}
@ -66,10 +67,10 @@ public final class AppendProcessor extends AbstractProcessor {
public static final class Factory implements Processor.Factory {
private final TemplateService templateService;
private final ScriptService scriptService;
public Factory(TemplateService templateService) {
this.templateService = templateService;
public Factory(ScriptService scriptService) {
this.scriptService = scriptService;
}
@Override
@ -77,9 +78,9 @@ public final class AppendProcessor extends AbstractProcessor {
Map<String, Object> config) throws Exception {
String field = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "field");
Object value = ConfigurationUtils.readObject(TYPE, processorTag, config, "value");
TemplateService.Template compiledTemplate = ConfigurationUtils.compileTemplate(TYPE, processorTag,
"field", field, templateService);
return new AppendProcessor(processorTag, compiledTemplate, ValueSource.wrap(value, templateService));
TemplateScript.Factory compiledTemplate = ConfigurationUtils.compileTemplate(TYPE, processorTag,
"field", field, scriptService);
return new AppendProcessor(processorTag, compiledTemplate, ValueSource.wrap(value, scriptService));
}
}
}

View File

@ -23,7 +23,8 @@ import org.elasticsearch.ingest.AbstractProcessor;
import org.elasticsearch.ingest.ConfigurationUtils;
import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.ingest.Processor;
import org.elasticsearch.ingest.TemplateService;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.TemplateScript;
import java.util.Map;
@ -35,14 +36,14 @@ public final class FailProcessor extends AbstractProcessor {
public static final String TYPE = "fail";
private final TemplateService.Template message;
private final TemplateScript.Factory message;
FailProcessor(String tag, TemplateService.Template message) {
FailProcessor(String tag, TemplateScript.Factory message) {
super(tag);
this.message = message;
}
public TemplateService.Template getMessage() {
public TemplateScript.Factory getMessage() {
return message;
}
@ -58,18 +59,18 @@ public final class FailProcessor extends AbstractProcessor {
public static final class Factory implements Processor.Factory {
private final TemplateService templateService;
private final ScriptService scriptService;
public Factory(TemplateService templateService) {
this.templateService = templateService;
public Factory(ScriptService scriptService) {
this.scriptService = scriptService;
}
@Override
public FailProcessor create(Map<String, Processor.Factory> registry, String processorTag,
Map<String, Object> config) throws Exception {
String message = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "message");
TemplateService.Template compiledTemplate = ConfigurationUtils.compileTemplate(TYPE, processorTag,
"message", message, templateService);
TemplateScript.Factory compiledTemplate = ConfigurationUtils.compileTemplate(TYPE, processorTag,
"message", message, scriptService);
return new FailProcessor(processorTag, compiledTemplate);
}
}

View File

@ -44,10 +44,10 @@ public class IngestCommonPlugin extends Plugin implements IngestPlugin {
public Map<String, Processor.Factory> getProcessors(Processor.Parameters parameters) {
Map<String, Processor.Factory> processors = new HashMap<>();
processors.put(DateProcessor.TYPE, new DateProcessor.Factory());
processors.put(SetProcessor.TYPE, new SetProcessor.Factory(parameters.templateService));
processors.put(AppendProcessor.TYPE, new AppendProcessor.Factory(parameters.templateService));
processors.put(SetProcessor.TYPE, new SetProcessor.Factory(parameters.scriptService));
processors.put(AppendProcessor.TYPE, new AppendProcessor.Factory(parameters.scriptService));
processors.put(RenameProcessor.TYPE, new RenameProcessor.Factory());
processors.put(RemoveProcessor.TYPE, new RemoveProcessor.Factory(parameters.templateService));
processors.put(RemoveProcessor.TYPE, new RemoveProcessor.Factory(parameters.scriptService));
processors.put(SplitProcessor.TYPE, new SplitProcessor.Factory());
processors.put(JoinProcessor.TYPE, new JoinProcessor.Factory());
processors.put(UppercaseProcessor.TYPE, new UppercaseProcessor.Factory());
@ -55,7 +55,7 @@ public class IngestCommonPlugin extends Plugin implements IngestPlugin {
processors.put(TrimProcessor.TYPE, new TrimProcessor.Factory());
processors.put(ConvertProcessor.TYPE, new ConvertProcessor.Factory());
processors.put(GsubProcessor.TYPE, new GsubProcessor.Factory());
processors.put(FailProcessor.TYPE, new FailProcessor.Factory(parameters.templateService));
processors.put(FailProcessor.TYPE, new FailProcessor.Factory(parameters.scriptService));
processors.put(ForEachProcessor.TYPE, new ForEachProcessor.Factory());
processors.put(DateIndexNameProcessor.TYPE, new DateIndexNameProcessor.Factory());
processors.put(SortProcessor.TYPE, new SortProcessor.Factory());

View File

@ -23,7 +23,8 @@ import org.elasticsearch.ingest.AbstractProcessor;
import org.elasticsearch.ingest.ConfigurationUtils;
import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.ingest.Processor;
import org.elasticsearch.ingest.TemplateService;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.TemplateScript;
import java.util.ArrayList;
import java.util.List;
@ -37,14 +38,14 @@ public final class RemoveProcessor extends AbstractProcessor {
public static final String TYPE = "remove";
private final List<TemplateService.Template> fields;
private final List<TemplateScript.Factory> fields;
RemoveProcessor(String tag, List<TemplateService.Template> fields) {
RemoveProcessor(String tag, List<TemplateScript.Factory> fields) {
super(tag);
this.fields = new ArrayList<>(fields);
}
public List<TemplateService.Template> getFields() {
public List<TemplateScript.Factory> getFields() {
return fields;
}
@ -60,10 +61,10 @@ public final class RemoveProcessor extends AbstractProcessor {
public static final class Factory implements Processor.Factory {
private final TemplateService templateService;
private final ScriptService scriptService;
public Factory(TemplateService templateService) {
this.templateService = templateService;
public Factory(ScriptService scriptService) {
this.scriptService = scriptService;
}
@Override
@ -77,8 +78,8 @@ public final class RemoveProcessor extends AbstractProcessor {
fields.add((String) field);
}
final List<TemplateService.Template> compiledTemplates = fields.stream()
.map(f -> ConfigurationUtils.compileTemplate(TYPE, processorTag, "field", f, templateService))
final List<TemplateScript.Factory> compiledTemplates = fields.stream()
.map(f -> ConfigurationUtils.compileTemplate(TYPE, processorTag, "field", f, scriptService))
.collect(Collectors.toList());
return new RemoveProcessor(processorTag, compiledTemplates);
}

View File

@ -23,8 +23,9 @@ import org.elasticsearch.ingest.AbstractProcessor;
import org.elasticsearch.ingest.ConfigurationUtils;
import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.ingest.Processor;
import org.elasticsearch.ingest.TemplateService;
import org.elasticsearch.ingest.ValueSource;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.TemplateScript;
import java.util.Map;
@ -37,14 +38,14 @@ public final class SetProcessor extends AbstractProcessor {
public static final String TYPE = "set";
private final boolean overrideEnabled;
private final TemplateService.Template field;
private final TemplateScript.Factory field;
private final ValueSource value;
SetProcessor(String tag, TemplateService.Template field, ValueSource value) {
SetProcessor(String tag, TemplateScript.Factory field, ValueSource value) {
this(tag, field, value, true);
}
SetProcessor(String tag, TemplateService.Template field, ValueSource value, boolean overrideEnabled) {
SetProcessor(String tag, TemplateScript.Factory field, ValueSource value, boolean overrideEnabled) {
super(tag);
this.overrideEnabled = overrideEnabled;
this.field = field;
@ -55,7 +56,7 @@ public final class SetProcessor extends AbstractProcessor {
return overrideEnabled;
}
public TemplateService.Template getField() {
public TemplateScript.Factory getField() {
return field;
}
@ -77,10 +78,10 @@ public final class SetProcessor extends AbstractProcessor {
public static final class Factory implements Processor.Factory {
private final TemplateService templateService;
private final ScriptService scriptService;
public Factory(TemplateService templateService) {
this.templateService = templateService;
public Factory(ScriptService scriptService) {
this.scriptService = scriptService;
}
@Override
@ -89,12 +90,12 @@ public final class SetProcessor extends AbstractProcessor {
String field = ConfigurationUtils.readStringProperty(TYPE, processorTag, config, "field");
Object value = ConfigurationUtils.readObject(TYPE, processorTag, config, "value");
boolean overrideEnabled = ConfigurationUtils.readBooleanProperty(TYPE, processorTag, config, "override", true);
TemplateService.Template compiledTemplate = ConfigurationUtils.compileTemplate(TYPE, processorTag,
"field", field, templateService);
TemplateScript.Factory compiledTemplate = ConfigurationUtils.compileTemplate(TYPE, processorTag,
"field", field, scriptService);
return new SetProcessor(
processorTag,
compiledTemplate,
ValueSource.wrap(value, templateService),
ValueSource.wrap(value, scriptService),
overrideEnabled);
}
}

View File

@ -22,6 +22,7 @@ package org.elasticsearch.ingest.common;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.ingest.TestTemplateService;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.test.ESTestCase;
import org.junit.Before;
@ -31,6 +32,7 @@ import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.mockito.Mockito.mock;
public class AppendProcessorFactoryTests extends ESTestCase {
@ -54,7 +56,7 @@ public class AppendProcessorFactoryTests extends ESTestCase {
String processorTag = randomAlphaOfLength(10);
AppendProcessor appendProcessor = factory.create(null, processorTag, config);
assertThat(appendProcessor.getTag(), equalTo(processorTag));
assertThat(appendProcessor.getField().execute(Collections.emptyMap()), equalTo("field1"));
assertThat(appendProcessor.getField().newInstance(Collections.emptyMap()).execute(), equalTo("field1"));
assertThat(appendProcessor.getValue().copyAndResolve(Collections.emptyMap()), equalTo(value));
}

View File

@ -22,7 +22,6 @@ package org.elasticsearch.ingest.common;
import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.ingest.Processor;
import org.elasticsearch.ingest.RandomDocumentPicks;
import org.elasticsearch.ingest.TemplateService;
import org.elasticsearch.ingest.TestTemplateService;
import org.elasticsearch.ingest.ValueSource;
import org.elasticsearch.test.ESTestCase;
@ -157,9 +156,9 @@ public class AppendProcessorTests extends ESTestCase {
}
private static Processor createAppendProcessor(String fieldName, Object fieldValue) {
TemplateService templateService = TestTemplateService.instance();
return new AppendProcessor(randomAlphaOfLength(10), templateService.compile(fieldName), ValueSource.wrap(fieldValue,
templateService));
return new AppendProcessor(randomAlphaOfLength(10),
new TestTemplateService.MockTemplateScript.Factory(fieldName),
ValueSource.wrap(fieldValue, TestTemplateService.instance()));
}
private enum Scalar {

View File

@ -46,7 +46,7 @@ public class FailProcessorFactoryTests extends ESTestCase {
String processorTag = randomAlphaOfLength(10);
FailProcessor failProcessor = factory.create(null, processorTag, config);
assertThat(failProcessor.getTag(), equalTo(processorTag));
assertThat(failProcessor.getMessage().execute(Collections.emptyMap()), equalTo("error"));
assertThat(failProcessor.getMessage().newInstance(Collections.emptyMap()).execute(), equalTo("error"));
}
public void testCreateMissingMessageField() throws Exception {

View File

@ -32,7 +32,8 @@ public class FailProcessorTests extends ESTestCase {
public void test() throws Exception {
IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random());
String message = randomAlphaOfLength(10);
Processor processor = new FailProcessor(randomAlphaOfLength(10), new TestTemplateService.MockTemplate(message));
Processor processor = new FailProcessor(randomAlphaOfLength(10),
new TestTemplateService.MockTemplateScript.Factory(message));
try {
processor.execute(ingestDocument);
fail("fail processor should throw an exception");

View File

@ -22,9 +22,9 @@ package org.elasticsearch.ingest.common;
import org.elasticsearch.ingest.CompoundProcessor;
import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.ingest.Processor;
import org.elasticsearch.ingest.TemplateService;
import org.elasticsearch.ingest.TestProcessor;
import org.elasticsearch.ingest.TestTemplateService;
import org.elasticsearch.script.TemplateScript;
import org.elasticsearch.test.ESTestCase;
import java.util.ArrayList;
@ -134,10 +134,10 @@ public class ForEachProcessorTests extends ESTestCase {
document.put("other", "value");
IngestDocument ingestDocument = new IngestDocument("_index", "_type", "_id", null, null, document);
TemplateService ts = TestTemplateService.instance();
ForEachProcessor processor = new ForEachProcessor(
"_tag", "values", new SetProcessor("_tag", ts.compile("_ingest._value.new_field"), (model) -> model.get("other"))
);
"_tag", "values", new SetProcessor("_tag",
new TestTemplateService.MockTemplateScript.Factory("_ingest._value.new_field"),
(model) -> model.get("other")));
processor.execute(ingestDocument);
assertThat(ingestDocument.getFieldValue("values.0.new_field", String.class), equalTo("value"));
@ -193,13 +193,12 @@ public class ForEachProcessorTests extends ESTestCase {
"_index", "_type", "_id", null, null, Collections.singletonMap("values", values)
);
TemplateService ts = TestTemplateService.instance();
TemplateScript.Factory template = new TestTemplateService.MockTemplateScript.Factory("errors");
ForEachProcessor processor = new ForEachProcessor(
"_tag", "values", new CompoundProcessor(false,
Collections.singletonList(new UppercaseProcessor("_tag_upper", "_ingest._value", false)),
Collections.singletonList(new AppendProcessor("_tag",
ts.compile("errors"), (model) -> (Collections.singletonList("added"))))
Collections.singletonList(new AppendProcessor("_tag", template, (model) -> (Collections.singletonList("added"))))
));
processor.execute(ingestDocument);

View File

@ -48,7 +48,7 @@ public class RemoveProcessorFactoryTests extends ESTestCase {
String processorTag = randomAlphaOfLength(10);
RemoveProcessor removeProcessor = factory.create(null, processorTag, config);
assertThat(removeProcessor.getTag(), equalTo(processorTag));
assertThat(removeProcessor.getFields().get(0).execute(Collections.emptyMap()), equalTo("field1"));
assertThat(removeProcessor.getFields().get(0).newInstance(Collections.emptyMap()).execute(), equalTo("field1"));
}
public void testCreateMultipleFields() throws Exception {
@ -58,7 +58,7 @@ public class RemoveProcessorFactoryTests extends ESTestCase {
RemoveProcessor removeProcessor = factory.create(null, processorTag, config);
assertThat(removeProcessor.getTag(), equalTo(processorTag));
assertThat(removeProcessor.getFields().stream()
.map(template -> template.execute(Collections.emptyMap()))
.map(template -> template.newInstance(Collections.emptyMap()).execute())
.collect(Collectors.toList()), equalTo(Arrays.asList("field1", "field2")));
}

View File

@ -37,7 +37,7 @@ public class RemoveProcessorTests extends ESTestCase {
IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random());
String field = RandomDocumentPicks.randomExistingFieldName(random(), ingestDocument);
Processor processor = new RemoveProcessor(randomAlphaOfLength(10),
Collections.singletonList(new TestTemplateService.MockTemplate(field)));
Collections.singletonList(new TestTemplateService.MockTemplateScript.Factory(field)));
processor.execute(ingestDocument);
assertThat(ingestDocument.hasField(field), equalTo(false));
}
@ -46,7 +46,7 @@ public class RemoveProcessorTests extends ESTestCase {
IngestDocument ingestDocument = RandomDocumentPicks.randomIngestDocument(random(), new HashMap<>());
String fieldName = RandomDocumentPicks.randomFieldName(random());
Processor processor = new RemoveProcessor(randomAlphaOfLength(10),
Collections.singletonList(new TestTemplateService.MockTemplate(fieldName)));
Collections.singletonList(new TestTemplateService.MockTemplateScript.Factory(fieldName)));
try {
processor.execute(ingestDocument);
fail("remove field should have failed");

View File

@ -47,7 +47,7 @@ public class SetProcessorFactoryTests extends ESTestCase {
String processorTag = randomAlphaOfLength(10);
SetProcessor setProcessor = factory.create(null, processorTag, config);
assertThat(setProcessor.getTag(), equalTo(processorTag));
assertThat(setProcessor.getField().execute(Collections.emptyMap()), equalTo("field1"));
assertThat(setProcessor.getField().newInstance(Collections.emptyMap()).execute(), equalTo("field1"));
assertThat(setProcessor.getValue().copyAndResolve(Collections.emptyMap()), equalTo("value1"));
assertThat(setProcessor.isOverrideEnabled(), equalTo(true));
}
@ -61,7 +61,7 @@ public class SetProcessorFactoryTests extends ESTestCase {
String processorTag = randomAlphaOfLength(10);
SetProcessor setProcessor = factory.create(null, processorTag, config);
assertThat(setProcessor.getTag(), equalTo(processorTag));
assertThat(setProcessor.getField().execute(Collections.emptyMap()), equalTo("field1"));
assertThat(setProcessor.getField().newInstance(Collections.emptyMap()).execute(), equalTo("field1"));
assertThat(setProcessor.getValue().copyAndResolve(Collections.emptyMap()), equalTo("value1"));
assertThat(setProcessor.isOverrideEnabled(), equalTo(overrideEnabled));
}

View File

@ -22,7 +22,6 @@ package org.elasticsearch.ingest.common;
import org.elasticsearch.ingest.IngestDocument;
import org.elasticsearch.ingest.Processor;
import org.elasticsearch.ingest.RandomDocumentPicks;
import org.elasticsearch.ingest.TemplateService;
import org.elasticsearch.ingest.TestTemplateService;
import org.elasticsearch.ingest.ValueSource;
import org.elasticsearch.test.ESTestCase;
@ -109,8 +108,7 @@ public class SetProcessorTests extends ESTestCase {
}
private static Processor createSetProcessor(String fieldName, Object fieldValue, boolean overrideEnabled) {
TemplateService templateService = TestTemplateService.instance();
return new SetProcessor(randomAlphaOfLength(10), templateService.compile(fieldName),
ValueSource.wrap(fieldValue, templateService), overrideEnabled);
return new SetProcessor(randomAlphaOfLength(10), new TestTemplateService.MockTemplateScript.Factory(fieldName),
ValueSource.wrap(fieldValue, TestTemplateService.instance()), overrideEnabled);
}
}

View File

@ -20,10 +20,12 @@
package org.elasticsearch.ingest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.script.ScriptContext;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptEngine;
import org.elasticsearch.script.ScriptModule;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.script.TemplateScript;
import org.elasticsearch.script.mustache.MustacheScriptEngine;
import org.elasticsearch.test.ESTestCase;
import org.junit.Before;
@ -31,16 +33,21 @@ import org.junit.Before;
import java.util.Collections;
import java.util.Map;
import static org.elasticsearch.script.Script.DEFAULT_TEMPLATE_LANG;
public abstract class AbstractScriptTestCase extends ESTestCase {
protected TemplateService templateService;
protected ScriptService scriptService;
@Before
public void init() throws Exception {
MustacheScriptEngine engine = new MustacheScriptEngine();
Map<String, ScriptEngine> engines = Collections.singletonMap(engine.getType(), engine);
ScriptService scriptService = new ScriptService(Settings.EMPTY, engines, ScriptModule.CORE_CONTEXTS);
templateService = new InternalTemplateService(scriptService);
scriptService = new ScriptService(Settings.EMPTY, engines, ScriptModule.CORE_CONTEXTS);
}
protected TemplateScript.Factory compile(String template) {
Script script = new Script(ScriptType.INLINE, DEFAULT_TEMPLATE_LANG, template, Collections.emptyMap());
return scriptService.compile(script, TemplateScript.CONTEXT);
}
}

View File

@ -34,10 +34,10 @@ public class IngestDocumentMustacheIT extends AbstractScriptTestCase {
Map<String, Object> document = new HashMap<>();
document.put("foo", "bar");
IngestDocument ingestDocument = new IngestDocument("index", "type", "id", null, null, document);
ingestDocument.setFieldValue(templateService.compile("field1"), ValueSource.wrap("1 {{foo}}", templateService));
ingestDocument.setFieldValue(compile("field1"), ValueSource.wrap("1 {{foo}}", scriptService));
assertThat(ingestDocument.getFieldValue("field1", String.class), equalTo("1 bar"));
ingestDocument.setFieldValue(templateService.compile("field1"), ValueSource.wrap("2 {{_source.foo}}", templateService));
ingestDocument.setFieldValue(compile("field1"), ValueSource.wrap("2 {{_source.foo}}", scriptService));
assertThat(ingestDocument.getFieldValue("field1", String.class), equalTo("2 bar"));
}
@ -49,12 +49,12 @@ public class IngestDocumentMustacheIT extends AbstractScriptTestCase {
innerObject.put("qux", Collections.singletonMap("fubar", "hello qux and fubar"));
document.put("foo", innerObject);
IngestDocument ingestDocument = new IngestDocument("index", "type", "id", null, null, document);
ingestDocument.setFieldValue(templateService.compile("field1"),
ValueSource.wrap("1 {{foo.bar}} {{foo.baz}} {{foo.qux.fubar}}", templateService));
ingestDocument.setFieldValue(compile("field1"),
ValueSource.wrap("1 {{foo.bar}} {{foo.baz}} {{foo.qux.fubar}}", scriptService));
assertThat(ingestDocument.getFieldValue("field1", String.class), equalTo("1 hello bar hello baz hello qux and fubar"));
ingestDocument.setFieldValue(templateService.compile("field1"),
ValueSource.wrap("2 {{_source.foo.bar}} {{_source.foo.baz}} {{_source.foo.qux.fubar}}", templateService));
ingestDocument.setFieldValue(compile("field1"),
ValueSource.wrap("2 {{_source.foo.bar}} {{_source.foo.baz}} {{_source.foo.qux.fubar}}", scriptService));
assertThat(ingestDocument.getFieldValue("field1", String.class), equalTo("2 hello bar hello baz hello qux and fubar"));
}
@ -68,7 +68,7 @@ public class IngestDocumentMustacheIT extends AbstractScriptTestCase {
list.add(null);
document.put("list2", list);
IngestDocument ingestDocument = new IngestDocument("index", "type", "id", null, null, document);
ingestDocument.setFieldValue(templateService.compile("field1"), ValueSource.wrap("1 {{list1.0}} {{list2.0}}", templateService));
ingestDocument.setFieldValue(compile("field1"), ValueSource.wrap("1 {{list1.0}} {{list2.0}}", scriptService));
assertThat(ingestDocument.getFieldValue("field1", String.class), equalTo("1 foo {field=value}"));
}
@ -78,8 +78,8 @@ public class IngestDocumentMustacheIT extends AbstractScriptTestCase {
ingestMap.put("timestamp", "bogus_timestamp");
document.put("_ingest", ingestMap);
IngestDocument ingestDocument = new IngestDocument("index", "type", "id", null, null, document);
ingestDocument.setFieldValue(templateService.compile("ingest_timestamp"),
ValueSource.wrap("{{_ingest.timestamp}} and {{_source._ingest.timestamp}}", templateService));
ingestDocument.setFieldValue(compile("ingest_timestamp"),
ValueSource.wrap("{{_ingest.timestamp}} and {{_source._ingest.timestamp}}", scriptService));
assertThat(ingestDocument.getFieldValue("ingest_timestamp", String.class),
equalTo(ingestDocument.getIngestMetadata().get("timestamp") + " and bogus_timestamp"));
}

View File

@ -1,54 +0,0 @@
/*
* 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.ingest;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.Matchers.equalTo;
public class TemplateServiceIT extends AbstractScriptTestCase {
public void testTemplates() {
Map<String, Object> model = new HashMap<>();
model.put("fielda", "value1");
model.put("fieldb", Collections.singletonMap("fieldc", "value3"));
TemplateService.Template template = templateService.compile("{{fielda}}/{{fieldb}}/{{fieldb.fieldc}}");
assertThat(template.execute(model), equalTo("value1/{fieldc=value3}/value3"));
}
public void testWrongTemplateUsage() {
Map<String, Object> model = Collections.emptyMap();
TemplateService.Template template = templateService.compile("value");
assertThat(template.execute(model), equalTo("value"));
template = templateService.compile("value {{");
assertThat(template.execute(model), equalTo("value {{"));
template = templateService.compile("value {{abc");
assertThat(template.execute(model), equalTo("value {{abc"));
template = templateService.compile("value }}");
assertThat(template.execute(model), equalTo("value }}"));
template = templateService.compile("value }} {{");
assertThat(template.execute(model), equalTo("value }} {{"));
}
}

View File

@ -36,11 +36,11 @@ public class ValueSourceMustacheIT extends AbstractScriptTestCase {
model.put("field1", "value1");
model.put("field2", Collections.singletonMap("field3", "value3"));
ValueSource valueSource = ValueSource.wrap("{{field1}}/{{field2}}/{{field2.field3}}", templateService);
ValueSource valueSource = ValueSource.wrap("{{field1}}/{{field2}}/{{field2.field3}}", scriptService);
assertThat(valueSource, instanceOf(ValueSource.TemplatedValue.class));
assertThat(valueSource.copyAndResolve(model), equalTo("value1/{field3=value3}/value3"));
valueSource = ValueSource.wrap(Arrays.asList("_value", "{{field1}}"), templateService);
valueSource = ValueSource.wrap(Arrays.asList("_value", "{{field1}}"), scriptService);
assertThat(valueSource, instanceOf(ValueSource.ListValue.class));
@SuppressWarnings("unchecked")
List<String> result = (List<String>) valueSource.copyAndResolve(model);
@ -52,7 +52,7 @@ public class ValueSourceMustacheIT extends AbstractScriptTestCase {
map.put("field1", "{{field1}}");
map.put("field2", Collections.singletonMap("field3", "{{field2.field3}}"));
map.put("field4", "_value");
valueSource = ValueSource.wrap(map, templateService);
valueSource = ValueSource.wrap(map, scriptService);
assertThat(valueSource, instanceOf(ValueSource.MapValue.class));
@SuppressWarnings("unchecked")
Map<String, Object> resultMap = (Map<String, Object>) valueSource.copyAndResolve(model);
@ -66,9 +66,9 @@ public class ValueSourceMustacheIT extends AbstractScriptTestCase {
public void testAccessSourceViaTemplate() {
IngestDocument ingestDocument = new IngestDocument("marvel", "type", "id", null, null, new HashMap<>());
assertThat(ingestDocument.hasField("marvel"), is(false));
ingestDocument.setFieldValue(templateService.compile("{{_index}}"), ValueSource.wrap("{{_index}}", templateService));
ingestDocument.setFieldValue(compile("{{_index}}"), ValueSource.wrap("{{_index}}", scriptService));
assertThat(ingestDocument.getFieldValue("marvel", String.class), equalTo("marvel"));
ingestDocument.removeField(templateService.compile("{{marvel}}"));
ingestDocument.removeField(compile("{{marvel}}"));
assertThat(ingestDocument.hasField("index"), is(false));
}

View File

@ -19,48 +19,70 @@
package org.elasticsearch.ingest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.script.MockScriptEngine;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptContext;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.TemplateScript;
import java.util.Collections;
import java.util.Map;
public class TestTemplateService implements TemplateService {
import static org.elasticsearch.script.Script.DEFAULT_TEMPLATE_LANG;
public class TestTemplateService extends ScriptService {
private boolean compilationException;
public static TemplateService instance() {
public static ScriptService instance() {
return new TestTemplateService(false);
}
public static TemplateService instance(boolean compilationException) {
public static ScriptService instance(boolean compilationException) {
return new TestTemplateService(compilationException);
}
private TestTemplateService(boolean compilationException) {
super(Settings.EMPTY, Collections.singletonMap(DEFAULT_TEMPLATE_LANG,
new MockScriptEngine(MockScriptEngine.NAME, Collections.emptyMap())), Collections.emptyMap());
this.compilationException = compilationException;
}
@Override
public Template compile(String template) {
public <FactoryType> FactoryType compile(Script script, ScriptContext<FactoryType> context) {
if (this.compilationException) {
throw new RuntimeException("could not compile script");
} else {
return new MockTemplate(template);
return (FactoryType) new MockTemplateScript.Factory(script.getIdOrCode());
}
}
public static class MockTemplate implements TemplateService.Template {
public static class MockTemplateScript extends TemplateScript {
private final String expected;
public MockTemplate(String expected) {
MockTemplateScript(String expected) {
super(Collections.emptyMap());
this.expected = expected;
}
@Override
public String execute(Map<String, Object> model) {
public String execute() {
return expected;
}
@Override
public String getKey() {
return expected;
public static class Factory implements TemplateScript.Factory {
private final String expected;
public Factory(String expected) {
this.expected = expected;
}
@Override
public TemplateScript newInstance(Map<String, Object> params) {
return new MockTemplateScript(expected);
}
}
}
}