refactor mustache to lang-mustache plugin. No rest tests yet.

This commit is contained in:
Robert Muir 2015-12-08 22:45:21 -05:00
parent 23aeaa88b2
commit 2e299860e5
31 changed files with 209 additions and 93 deletions

View File

@ -65,7 +65,6 @@ public class PluginBuildPlugin extends BuildPlugin {
// with a full elasticsearch server that includes optional deps // with a full elasticsearch server that includes optional deps
provided "com.spatial4j:spatial4j:${project.versions.spatial4j}" provided "com.spatial4j:spatial4j:${project.versions.spatial4j}"
provided "com.vividsolutions:jts:${project.versions.jts}" provided "com.vividsolutions:jts:${project.versions.jts}"
provided "com.github.spullara.mustache.java:compiler:${project.versions.mustache}"
provided "log4j:log4j:${project.versions.log4j}" provided "log4j:log4j:${project.versions.log4j}"
provided "log4j:apache-log4j-extras:${project.versions.log4j}" provided "log4j:apache-log4j-extras:${project.versions.log4j}"
provided "org.slf4j:slf4j-api:${project.versions.slf4j}" provided "org.slf4j:slf4j-api:${project.versions.slf4j}"

View File

@ -4,7 +4,6 @@ lucene = 5.4.0-snapshot-1715952
# optional dependencies # optional dependencies
spatial4j = 0.5 spatial4j = 0.5
jts = 1.13 jts = 1.13
mustache = 0.9.1
jackson = 2.6.2 jackson = 2.6.2
log4j = 1.2.17 log4j = 1.2.17
slf4j = 1.6.2 slf4j = 1.6.2

View File

@ -74,9 +74,6 @@ dependencies {
compile "com.spatial4j:spatial4j:${versions.spatial4j}", optional compile "com.spatial4j:spatial4j:${versions.spatial4j}", optional
compile "com.vividsolutions:jts:${versions.jts}", optional compile "com.vividsolutions:jts:${versions.jts}", optional
// templating
compile "com.github.spullara.mustache.java:compiler:${versions.mustache}", optional
// logging // logging
compile "log4j:log4j:${versions.log4j}", optional compile "log4j:log4j:${versions.log4j}", optional
compile "log4j:apache-log4j-extras:${versions.log4j}", optional compile "log4j:apache-log4j-extras:${versions.log4j}", optional

View File

@ -18,25 +18,15 @@
*/ */
package org.elasticsearch.index.query; package org.elasticsearch.index.query;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.HasContextAndHeaders;
import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.lease.Releasables;
import org.elasticsearch.common.xcontent.XContent;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.script.*; import org.elasticsearch.script.*;
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static org.elasticsearch.common.Strings.hasLength;
/** /**
* In the simplest case, parse template string and variables from the request, * In the simplest case, parse template string and variables from the request,
* compile the template and execute the template against the given variables. * compile the template and execute the template against the given variables.

View File

@ -41,7 +41,6 @@ import org.elasticsearch.rest.action.support.RestBuilderListener;
import org.elasticsearch.script.Script.ScriptField; import org.elasticsearch.script.Script.ScriptField;
import org.elasticsearch.script.ScriptService.ScriptType; import org.elasticsearch.script.ScriptService.ScriptType;
import org.elasticsearch.script.Template; import org.elasticsearch.script.Template;
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
import java.util.Map; import java.util.Map;
@ -89,7 +88,7 @@ public class RestRenderSearchTemplateAction extends BaseRestHandler {
throw new ElasticsearchParseException("failed to parse request. unknown field [{}] of type [{}]", currentFieldName, token); throw new ElasticsearchParseException("failed to parse request. unknown field [{}] of type [{}]", currentFieldName, token);
} }
} }
template = new Template(templateId, ScriptType.INDEXED, MustacheScriptEngineService.NAME, null, params); template = new Template(templateId, ScriptType.INDEXED, Template.DEFAULT_LANG, null, params);
} }
renderSearchTemplateRequest = new RenderSearchTemplateRequest(); renderSearchTemplateRequest = new RenderSearchTemplateRequest();
renderSearchTemplateRequest.template(template); renderSearchTemplateRequest.template(template);

View File

@ -24,7 +24,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.script.RestDeleteIndexedScriptAction; import org.elasticsearch.rest.action.script.RestDeleteIndexedScriptAction;
import org.elasticsearch.script.mustache.MustacheScriptEngineService; import org.elasticsearch.script.Template;
import static org.elasticsearch.rest.RestRequest.Method.DELETE; import static org.elasticsearch.rest.RestRequest.Method.DELETE;
@ -38,6 +38,6 @@ public class RestDeleteSearchTemplateAction extends RestDeleteIndexedScriptActio
@Override @Override
protected String getScriptLang(RestRequest request) { protected String getScriptLang(RestRequest request) {
return MustacheScriptEngineService.NAME; return Template.DEFAULT_LANG;
} }
} }

View File

@ -25,7 +25,7 @@ import org.elasticsearch.common.xcontent.XContentBuilderString;
import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.script.RestGetIndexedScriptAction; import org.elasticsearch.rest.action.script.RestGetIndexedScriptAction;
import org.elasticsearch.script.mustache.MustacheScriptEngineService; import org.elasticsearch.script.Template;
import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestRequest.Method.GET;
@ -42,7 +42,7 @@ public class RestGetSearchTemplateAction extends RestGetIndexedScriptAction {
@Override @Override
protected String getScriptLang(RestRequest request) { protected String getScriptLang(RestRequest request) {
return MustacheScriptEngineService.NAME; return Template.DEFAULT_LANG;
} }
@Override @Override

View File

@ -23,7 +23,7 @@ import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.*; import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.script.RestPutIndexedScriptAction; import org.elasticsearch.rest.action.script.RestPutIndexedScriptAction;
import org.elasticsearch.script.mustache.MustacheScriptEngineService; import org.elasticsearch.script.Template;
import static org.elasticsearch.rest.RestRequest.Method.POST; import static org.elasticsearch.rest.RestRequest.Method.POST;
import static org.elasticsearch.rest.RestRequest.Method.PUT; import static org.elasticsearch.rest.RestRequest.Method.PUT;
@ -59,6 +59,6 @@ public class RestPutSearchTemplateAction extends RestPutIndexedScriptAction {
@Override @Override
protected String getScriptLang(RestRequest request) { protected String getScriptLang(RestRequest request) {
return MustacheScriptEngineService.NAME; return Template.DEFAULT_LANG;
} }
} }

View File

@ -22,9 +22,7 @@ package org.elasticsearch.script;
import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.inject.AbstractModule;
import org.elasticsearch.common.inject.multibindings.MapBinder; import org.elasticsearch.common.inject.multibindings.MapBinder;
import org.elasticsearch.common.inject.multibindings.Multibinder; import org.elasticsearch.common.inject.multibindings.Multibinder;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -75,13 +73,6 @@ public class ScriptModule extends AbstractModule {
Multibinder<ScriptEngineService> multibinder = Multibinder.newSetBinder(binder(), ScriptEngineService.class); Multibinder<ScriptEngineService> multibinder = Multibinder.newSetBinder(binder(), ScriptEngineService.class);
multibinder.addBinding().to(NativeScriptEngineService.class); multibinder.addBinding().to(NativeScriptEngineService.class);
try {
Class.forName("com.github.mustachejava.Mustache");
multibinder.addBinding().to(MustacheScriptEngineService.class).asEagerSingleton();
} catch (Throwable t) {
Loggers.getLogger(ScriptService.class, settings).debug("failed to load mustache", t);
}
for (Class<? extends ScriptEngineService> scriptEngine : scriptEngines) { for (Class<? extends ScriptEngineService> scriptEngine : scriptEngines) {
multibinder.addBinding().to(scriptEngine).asEagerSingleton(); multibinder.addBinding().to(scriptEngine).asEagerSingleton();

View File

@ -29,13 +29,15 @@ import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.script.ScriptService.ScriptType; import org.elasticsearch.script.ScriptService.ScriptType;
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
public class Template extends Script { public class Template extends Script {
/** Default templating language */
public static final String DEFAULT_LANG = "mustache";
private XContentType contentType; private XContentType contentType;
@ -51,7 +53,7 @@ public class Template extends Script {
* The inline template. * The inline template.
*/ */
public Template(String template) { public Template(String template) {
super(template, MustacheScriptEngineService.NAME); super(template, DEFAULT_LANG);
} }
/** /**
@ -73,7 +75,7 @@ public class Template extends Script {
*/ */
public Template(String template, ScriptType type, @Nullable String lang, @Nullable XContentType xContentType, public Template(String template, ScriptType type, @Nullable String lang, @Nullable XContentType xContentType,
@Nullable Map<String, Object> params) { @Nullable Map<String, Object> params) {
super(template, type, lang == null ? MustacheScriptEngineService.NAME : lang, params); super(template, type, lang == null ? DEFAULT_LANG : lang, params);
this.contentType = xContentType; this.contentType = xContentType;
} }
@ -120,16 +122,16 @@ public class Template extends Script {
} }
public static Script parse(Map<String, Object> config, boolean removeMatchedEntries, ParseFieldMatcher parseFieldMatcher) { public static Script parse(Map<String, Object> config, boolean removeMatchedEntries, ParseFieldMatcher parseFieldMatcher) {
return new TemplateParser(Collections.emptyMap(), MustacheScriptEngineService.NAME).parse(config, removeMatchedEntries, parseFieldMatcher); return new TemplateParser(Collections.emptyMap(), DEFAULT_LANG).parse(config, removeMatchedEntries, parseFieldMatcher);
} }
public static Template parse(XContentParser parser, ParseFieldMatcher parseFieldMatcher) throws IOException { public static Template parse(XContentParser parser, ParseFieldMatcher parseFieldMatcher) throws IOException {
return new TemplateParser(Collections.emptyMap(), MustacheScriptEngineService.NAME).parse(parser, parseFieldMatcher); return new TemplateParser(Collections.emptyMap(), DEFAULT_LANG).parse(parser, parseFieldMatcher);
} }
@Deprecated @Deprecated
public static Template parse(XContentParser parser, Map<String, ScriptType> additionalTemplateFieldNames, ParseFieldMatcher parseFieldMatcher) throws IOException { public static Template parse(XContentParser parser, Map<String, ScriptType> additionalTemplateFieldNames, ParseFieldMatcher parseFieldMatcher) throws IOException {
return new TemplateParser(additionalTemplateFieldNames, MustacheScriptEngineService.NAME).parse(parser, parseFieldMatcher); return new TemplateParser(additionalTemplateFieldNames, DEFAULT_LANG).parse(parser, parseFieldMatcher);
} }
@Deprecated @Deprecated
@ -172,7 +174,7 @@ public class Template extends Script {
@Override @Override
protected Template createSimpleScript(XContentParser parser) throws IOException { protected Template createSimpleScript(XContentParser parser) throws IOException {
return new Template(String.valueOf(parser.objectText()), ScriptType.INLINE, MustacheScriptEngineService.NAME, contentType, null); return new Template(String.valueOf(parser.objectText()), ScriptType.INLINE, DEFAULT_LANG, contentType, null);
} }
@Override @Override

View File

@ -59,7 +59,6 @@ import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.script.ScriptContextRegistry; import org.elasticsearch.script.ScriptContextRegistry;
import org.elasticsearch.script.ScriptEngineService; import org.elasticsearch.script.ScriptEngineService;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.IndexSettingsModule; import org.elasticsearch.test.IndexSettingsModule;
import org.elasticsearch.test.engine.MockEngineFactory; import org.elasticsearch.test.engine.MockEngineFactory;
@ -102,7 +101,6 @@ public class IndexModuleTests extends ESTestCase {
BigArrays bigArrays = new BigArrays(recycler, circuitBreakerService); BigArrays bigArrays = new BigArrays(recycler, circuitBreakerService);
IndicesFieldDataCache indicesFieldDataCache = new IndicesFieldDataCache(settings, new IndicesFieldDataCacheListener(circuitBreakerService), threadPool); IndicesFieldDataCache indicesFieldDataCache = new IndicesFieldDataCache(settings, new IndicesFieldDataCacheListener(circuitBreakerService), threadPool);
Set<ScriptEngineService> scriptEngines = new HashSet<>(); Set<ScriptEngineService> scriptEngines = new HashSet<>();
scriptEngines.add(new MustacheScriptEngineService(settings));
scriptEngines.addAll(Arrays.asList(scriptEngineServices)); scriptEngines.addAll(Arrays.asList(scriptEngineServices));
ScriptService scriptService = new ScriptService(settings, environment, scriptEngines, new ResourceWatcherService(settings, threadPool), new ScriptContextRegistry(Collections.emptyList())); ScriptService scriptService = new ScriptService(settings, environment, scriptEngines, new ResourceWatcherService(settings, threadPool), new ScriptContextRegistry(Collections.emptyList()));
IndicesQueriesRegistry indicesQueriesRegistry = new IndicesQueriesRegistry(settings, Collections.emptySet(), new NamedWriteableRegistry()); IndicesQueriesRegistry indicesQueriesRegistry = new IndicesQueriesRegistry(settings, Collections.emptySet(), new NamedWriteableRegistry());

View File

@ -19,12 +19,9 @@
package org.elasticsearch.script; package org.elasticsearch.script;
import org.elasticsearch.common.ContextAndHeaderHolder; import org.elasticsearch.common.ContextAndHeaderHolder;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment; import org.elasticsearch.env.Environment;
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.junit.Test;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
@ -32,9 +29,6 @@ import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import static org.elasticsearch.common.settings.Settings.settingsBuilder;
import static org.hamcrest.Matchers.containsString;
// TODO: these really should just be part of ScriptService tests, there is nothing special about them // TODO: these really should just be part of ScriptService tests, there is nothing special about them
public class FileScriptTests extends ESTestCase { public class FileScriptTests extends ESTestCase {

View File

@ -22,7 +22,6 @@ package org.elasticsearch.script;
import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.script.ScriptService.ScriptType; import org.elasticsearch.script.ScriptService.ScriptType;
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.search.lookup.SearchLookup;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.junit.After; import org.junit.After;
@ -45,7 +44,7 @@ import static org.hamcrest.Matchers.containsString;
// TODO: this needs to be a base test class, and all scripting engines extend it // TODO: this needs to be a base test class, and all scripting engines extend it
public class ScriptModesTests extends ESTestCase { public class ScriptModesTests extends ESTestCase {
private static final Set<String> ALL_LANGS = unmodifiableSet( private static final Set<String> ALL_LANGS = unmodifiableSet(
newHashSet(MustacheScriptEngineService.NAME, "custom", "test")); newHashSet("custom", "test"));
static final String[] ENABLE_VALUES = new String[]{"on", "true", "yes", "1"}; static final String[] ENABLE_VALUES = new String[]{"on", "true", "yes", "1"};
static final String[] DISABLE_VALUES = new String[]{"off", "false", "no", "0"}; static final String[] DISABLE_VALUES = new String[]{"off", "false", "no", "0"};
@ -73,7 +72,6 @@ public class ScriptModesTests extends ESTestCase {
scriptContextRegistry = new ScriptContextRegistry(contexts.values()); scriptContextRegistry = new ScriptContextRegistry(contexts.values());
scriptContexts = scriptContextRegistry.scriptContexts().toArray(new ScriptContext[scriptContextRegistry.scriptContexts().size()]); scriptContexts = scriptContextRegistry.scriptContexts().toArray(new ScriptContext[scriptContextRegistry.scriptContexts().size()]);
scriptEngines = buildScriptEnginesByLangMap(newHashSet( scriptEngines = buildScriptEnginesByLangMap(newHashSet(
new MustacheScriptEngineService(Settings.EMPTY),
//add the native engine just to make sure it gets filtered out //add the native engine just to make sure it gets filtered out
new NativeScriptEngineService(Settings.EMPTY, Collections.<String, NativeScriptFactory>emptyMap()), new NativeScriptEngineService(Settings.EMPTY, Collections.<String, NativeScriptFactory>emptyMap()),
new CustomScriptEngineService())); new CustomScriptEngineService()));
@ -93,8 +91,8 @@ public class ScriptModesTests extends ESTestCase {
public void assertAllSettingsWereChecked() { public void assertAllSettingsWereChecked() {
if (assertScriptModesNonNull) { if (assertScriptModesNonNull) {
assertThat(scriptModes, notNullValue()); assertThat(scriptModes, notNullValue());
//3 is the number of engines (native excluded), custom is counted twice though as it's associated with two different names //2 is the number of engines (native excluded), custom is counted twice though as it's associated with two different names
int numberOfSettings = 3 * ScriptType.values().length * scriptContextRegistry.scriptContexts().size(); int numberOfSettings = 2 * ScriptType.values().length * scriptContextRegistry.scriptContexts().size();
assertThat(scriptModes.scriptModes.size(), equalTo(numberOfSettings)); assertThat(scriptModes.scriptModes.size(), equalTo(numberOfSettings));
if (assertAllSettingsWereChecked) { if (assertAllSettingsWereChecked) {
assertThat(checkedSettings.size(), equalTo(numberOfSettings)); assertThat(checkedSettings.size(), equalTo(numberOfSettings));
@ -190,21 +188,6 @@ public class ScriptModesTests extends ESTestCase {
assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INLINE}, complementOf); assertScriptModes(ScriptMode.SANDBOX, ALL_LANGS, new ScriptType[]{ScriptType.INLINE}, complementOf);
} }
public void testInteractionBetweenGenericAndEngineSpecificSettings() {
Settings.Builder builder = Settings.builder().put("script.inline", randomFrom(DISABLE_VALUES))
.put(specificEngineOpSettings(MustacheScriptEngineService.NAME, ScriptType.INLINE, ScriptContext.Standard.AGGS), randomFrom(ENABLE_VALUES))
.put(specificEngineOpSettings(MustacheScriptEngineService.NAME, ScriptType.INLINE, ScriptContext.Standard.SEARCH), randomFrom(ENABLE_VALUES));
Set<String> mustacheLangSet = singleton(MustacheScriptEngineService.NAME);
Set<String> allButMustacheLangSet = new HashSet<>(ALL_LANGS);
allButMustacheLangSet.remove(MustacheScriptEngineService.NAME);
this.scriptModes = new ScriptModes(scriptEngines, scriptContextRegistry, builder.build());
assertScriptModes(ScriptMode.ON, mustacheLangSet, new ScriptType[]{ScriptType.INLINE}, ScriptContext.Standard.AGGS, ScriptContext.Standard.SEARCH);
assertScriptModes(ScriptMode.OFF, mustacheLangSet, new ScriptType[]{ScriptType.INLINE}, complementOf(ScriptContext.Standard.AGGS, ScriptContext.Standard.SEARCH));
assertScriptModesAllOps(ScriptMode.OFF, allButMustacheLangSet, ScriptType.INLINE);
assertScriptModesAllOps(ScriptMode.SANDBOX, ALL_LANGS, ScriptType.INDEXED);
assertScriptModesAllOps(ScriptMode.ON, ALL_LANGS, ScriptType.FILE);
}
private void assertScriptModesAllOps(ScriptMode expectedScriptMode, Set<String> langs, ScriptType... scriptTypes) { private void assertScriptModesAllOps(ScriptMode expectedScriptMode, Set<String> langs, ScriptType... scriptTypes) {
assertScriptModes(expectedScriptMode, langs, scriptTypes, scriptContexts); assertScriptModes(expectedScriptMode, langs, scriptTypes, scriptContexts);
} }

View File

@ -25,7 +25,6 @@ import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment; import org.elasticsearch.env.Environment;
import org.elasticsearch.script.ScriptService.ScriptType; import org.elasticsearch.script.ScriptService.ScriptType;
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
import org.elasticsearch.search.lookup.SearchLookup; import org.elasticsearch.search.lookup.SearchLookup;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.watcher.ResourceWatcherService; import org.elasticsearch.watcher.ResourceWatcherService;
@ -73,8 +72,7 @@ public class ScriptServiceTests extends ESTestCase {
.put("path.conf", genericConfigFolder) .put("path.conf", genericConfigFolder)
.build(); .build();
resourceWatcherService = new ResourceWatcherService(baseSettings, null); resourceWatcherService = new ResourceWatcherService(baseSettings, null);
scriptEngineServices = newHashSet(new TestEngineService(), scriptEngineServices = newHashSet(new TestEngineService());
new MustacheScriptEngineService(baseSettings));
scriptEnginesByLangMap = ScriptModesTests.buildScriptEnginesByLangMap(scriptEngineServices); scriptEnginesByLangMap = ScriptModesTests.buildScriptEnginesByLangMap(scriptEngineServices);
//randomly register custom script contexts //randomly register custom script contexts
int randomInt = randomIntBetween(0, 3); int randomInt = randomIntBetween(0, 3);
@ -199,10 +197,6 @@ public class ScriptServiceTests extends ESTestCase {
createFileScripts("groovy", "mustache", "test"); createFileScripts("groovy", "mustache", "test");
for (ScriptContext scriptContext : scriptContexts) { for (ScriptContext scriptContext : scriptContexts) {
//mustache engine is sandboxed, all scripts are enabled by default
assertCompileAccepted(MustacheScriptEngineService.NAME, "script", ScriptType.INLINE, scriptContext, contextAndHeaders);
assertCompileAccepted(MustacheScriptEngineService.NAME, "script", ScriptType.INDEXED, scriptContext, contextAndHeaders);
assertCompileAccepted(MustacheScriptEngineService.NAME, "file_script", ScriptType.FILE, scriptContext, contextAndHeaders);
//custom engine is sandboxed, all scripts are enabled by default //custom engine is sandboxed, all scripts are enabled by default
assertCompileAccepted("test", "script", ScriptType.INLINE, scriptContext, contextAndHeaders); assertCompileAccepted("test", "script", ScriptType.INLINE, scriptContext, contextAndHeaders);
assertCompileAccepted("test", "script", ScriptType.INDEXED, scriptContext, contextAndHeaders); assertCompileAccepted("test", "script", ScriptType.INDEXED, scriptContext, contextAndHeaders);

View File

@ -0,0 +1,36 @@
/*
* 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.
*/
esplugin {
description 'Mustache scripting integration for Elasticsearch'
classname 'org.elasticsearch.script.mustache.MustachePlugin'
}
dependencies {
compile "com.github.spullara.mustache.java:compiler:0.9.1"
}
//compileTestJava.options.compilerArgs << '-Xlint:-rawtypes'
integTest {
cluster {
systemProperty 'es.script.inline', 'on'
systemProperty 'es.script.indexed', 'on'
}
}

View File

@ -0,0 +1,40 @@
/*
* 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.script.mustache;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.ScriptModule;
public class MustachePlugin extends Plugin {
@Override
public String name() {
return "lang-mustache";
}
@Override
public String description() {
return "Mustache scripting integration for Elasticsearch";
}
public void onModule(ScriptModule module) {
module.addScriptEngine(MustacheScriptEngineService.class);
}
}

View File

@ -19,19 +19,28 @@
package org.elasticsearch.index.query; package org.elasticsearch.index.query;
import com.carrotsearch.randomizedtesting.generators.RandomInts;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.AbstractQueryTestCase;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.query.TemplateQueryBuilder;
import org.elasticsearch.script.Script.ScriptParseException; import org.elasticsearch.script.Script.ScriptParseException;
import org.elasticsearch.script.ScriptService.ScriptType; import org.elasticsearch.script.ScriptService.ScriptType;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.script.Template; import org.elasticsearch.script.Template;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Random;
@ESTestCase.AwaitsFix(bugUrl = "nopush")
public class TemplateQueryBuilderTests extends AbstractQueryTestCase<TemplateQueryBuilder> { public class TemplateQueryBuilderTests extends AbstractQueryTestCase<TemplateQueryBuilder> {
/** /**
@ -41,7 +50,20 @@ public class TemplateQueryBuilderTests extends AbstractQueryTestCase<TemplateQue
@BeforeClass @BeforeClass
public static void setupClass() { public static void setupClass() {
templateBase = RandomQueryBuilder.createQuery(getRandom()); templateBase = createQuery(getRandom());
}
static QueryBuilder<?> createQuery(Random r) {
switch (RandomInts.randomIntBetween(r, 0, 2)) {
case 0:
return new MatchAllQueryBuilder();
case 1:
return new IdsQueryBuilder();
case 2:
return EmptyQueryBuilder.PROTOTYPE;
default:
throw new UnsupportedOperationException();
}
} }
@Override @Override

View File

@ -17,7 +17,7 @@
* under the License. * under the License.
*/ */
package org.elasticsearch.validate; package org.elasticsearch.messy.tests;
import org.elasticsearch.action.admin.cluster.validate.template.RenderSearchTemplateResponse; import org.elasticsearch.action.admin.cluster.validate.template.RenderSearchTemplateResponse;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
@ -25,11 +25,15 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.ScriptService.ScriptType; import org.elasticsearch.script.ScriptService.ScriptType;
import org.elasticsearch.script.Template; import org.elasticsearch.script.Template;
import org.elasticsearch.script.mustache.MustachePlugin;
import org.elasticsearch.script.mustache.MustacheScriptEngineService; import org.elasticsearch.script.mustache.MustacheScriptEngineService;
import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.ESIntegTestCase;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -37,10 +41,15 @@ import static org.elasticsearch.common.settings.Settings.settingsBuilder;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.notNullValue;
@ESIntegTestCase.SuiteScopeTestCase @ESIntegTestCase.SuiteScopeTestCase @ESIntegTestCase.AwaitsFix(bugUrl = "nopush")
public class RenderSearchTemplateIT extends ESIntegTestCase { public class RenderSearchTemplateTests extends ESIntegTestCase {
private static final String TEMPLATE_CONTENTS = "{\"size\":\"{{size}}\",\"query\":{\"match\":{\"foo\":\"{{value}}\"}},\"aggs\":{\"objects\":{\"terms\":{\"field\":\"{{value}}\",\"size\":\"{{size}}\"}}}}"; private static final String TEMPLATE_CONTENTS = "{\"size\":\"{{size}}\",\"query\":{\"match\":{\"foo\":\"{{value}}\"}},\"aggs\":{\"objects\":{\"terms\":{\"field\":\"{{value}}\",\"size\":\"{{size}}\"}}}}";
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Collections.singleton(MustachePlugin.class);
}
@Override @Override
protected void setupSuiteScopeCluster() throws Exception { protected void setupSuiteScopeCluster() throws Exception {
client().preparePutIndexedScript(MustacheScriptEngineService.NAME, "index_template_1", "{ \"template\": " + TEMPLATE_CONTENTS + " }").get(); client().preparePutIndexedScript(MustacheScriptEngineService.NAME, "index_template_1", "{ \"template\": " + TEMPLATE_CONTENTS + " }").get();

View File

@ -17,7 +17,7 @@
* under the License. * under the License.
*/ */
package org.elasticsearch.search.suggest; package org.elasticsearch.messy.tests;
import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchException;
@ -33,6 +33,10 @@ import org.elasticsearch.action.suggest.SuggestResponse;
import org.elasticsearch.common.io.PathUtils; import org.elasticsearch.common.io.PathUtils;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.mustache.MustachePlugin;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilder.SuggestionBuilder; import org.elasticsearch.search.suggest.SuggestBuilder.SuggestionBuilder;
import org.elasticsearch.search.suggest.phrase.PhraseSuggestionBuilder; import org.elasticsearch.search.suggest.phrase.PhraseSuggestionBuilder;
import org.elasticsearch.search.suggest.phrase.PhraseSuggestionBuilder.DirectCandidateGenerator; import org.elasticsearch.search.suggest.phrase.PhraseSuggestionBuilder.DirectCandidateGenerator;
@ -46,6 +50,7 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -76,7 +81,13 @@ import static org.hamcrest.Matchers.nullValue;
* possible these tests should declare for the first request, make the request, modify the configuration for the next request, make that * possible these tests should declare for the first request, make the request, modify the configuration for the next request, make that
* request, modify again, request again, etc. This makes it very obvious what changes between requests. * request, modify again, request again, etc. This makes it very obvious what changes between requests.
*/ */
public class SuggestSearchIT extends ESIntegTestCase { public class SuggestSearchTests extends ESIntegTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Collections.singleton(MustachePlugin.class);
}
// see #3196 // see #3196
public void testSuggestAcrossMultipleIndices() throws IOException { public void testSuggestAcrossMultipleIndices() throws IOException {
createIndex("test"); createIndex("test");
@ -609,7 +620,7 @@ public class SuggestSearchIT extends ESIntegTestCase {
} }
private List<String> readMarvelHeroNames() throws IOException, URISyntaxException { private List<String> readMarvelHeroNames() throws IOException, URISyntaxException {
return Files.readAllLines(PathUtils.get(SuggestSearchIT.class.getResource("/config/names.txt").toURI()), StandardCharsets.UTF_8); return Files.readAllLines(PathUtils.get(Suggest.class.getResource("/config/names.txt").toURI()), StandardCharsets.UTF_8);
} }
public void testSizePararm() throws IOException { public void testSizePararm() throws IOException {

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.elasticsearch.index.query; package org.elasticsearch.messy.tests;
import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
@ -45,6 +45,8 @@ import org.elasticsearch.index.analysis.AnalysisService;
import org.elasticsearch.index.cache.bitset.BitsetFilterCache; import org.elasticsearch.index.cache.bitset.BitsetFilterCache;
import org.elasticsearch.index.fielddata.IndexFieldDataService; import org.elasticsearch.index.fielddata.IndexFieldDataService;
import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.query.TemplateQueryParser;
import org.elasticsearch.index.query.functionscore.ScoreFunctionParser; import org.elasticsearch.index.query.functionscore.ScoreFunctionParser;
import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.index.similarity.SimilarityService; import org.elasticsearch.index.similarity.SimilarityService;
@ -74,6 +76,7 @@ import static org.hamcrest.Matchers.containsString;
* Test parsing and executing a template request. * Test parsing and executing a template request.
*/ */
// NOTE: this can't be migrated to ESSingleNodeTestCase because of the custom path.conf // NOTE: this can't be migrated to ESSingleNodeTestCase because of the custom path.conf
@ESTestCase.AwaitsFix(bugUrl = "nopush")
public class TemplateQueryParserTests extends ESTestCase { public class TemplateQueryParserTests extends ESTestCase {
private Injector injector; private Injector injector;
@ -89,7 +92,7 @@ public class TemplateQueryParserTests extends ESTestCase {
.build(); .build();
final Client proxy = (Client) Proxy.newProxyInstance( final Client proxy = (Client) Proxy.newProxyInstance(
Client.class.getClassLoader(), Client.class.getClassLoader(),
new Class[]{Client.class}, (proxy1, method, args) -> { new Class<?>[]{Client.class}, (proxy1, method, args) -> {
throw new UnsupportedOperationException("client is just a dummy"); throw new UnsupportedOperationException("client is just a dummy");
}); });
Index index = new Index("test"); Index index = new Index("test");

View File

@ -16,7 +16,7 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.elasticsearch.index.query; package org.elasticsearch.messy.tests;
import org.elasticsearch.action.index.IndexRequest.OpType; import org.elasticsearch.action.index.IndexRequest.OpType;
import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.index.IndexRequestBuilder;
@ -31,9 +31,14 @@ import org.elasticsearch.common.ParseFieldMatcher;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TemplateQueryBuilder;
import org.elasticsearch.index.query.TemplateQueryParser;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService;
import org.elasticsearch.script.ScriptService.ScriptType; import org.elasticsearch.script.ScriptService.ScriptType;
import org.elasticsearch.script.Template; import org.elasticsearch.script.Template;
import org.elasticsearch.script.mustache.MustachePlugin;
import org.elasticsearch.script.mustache.MustacheScriptEngineService; import org.elasticsearch.script.mustache.MustacheScriptEngineService;
import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.test.ESIntegTestCase;
@ -41,6 +46,8 @@ import org.junit.Before;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -58,7 +65,12 @@ import static org.hamcrest.Matchers.is;
* Full integration test of the template query plugin. * Full integration test of the template query plugin.
*/ */
@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.SUITE) @ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.SUITE)
public class TemplateQueryIT extends ESIntegTestCase { public class TemplateQueryTests extends ESIntegTestCase {
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Collections.singleton(MustachePlugin.class);
}
@Before @Before
public void setup() throws IOException { public void setup() throws IOException {

View File

@ -0,0 +1,44 @@
/*
* 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.
*/
/**
* This package contains tests that use mustache to test what looks
* to be unrelated functionality, or functionality that should be
* tested with a mock instead. Instead of doing an epic battle
* with these tests, they are temporarily moved here to the mustache
* module's tests, but that is likely not where they belong. Please
* help by cleaning them up and we can remove this package!
*
* <ul>
* <li>If the test is actually testing mustache specifically, move to
* the org.elasticsearch.script.mustache tests package of this module</li>
* <li>If the test is testing templating integration with another core subsystem,
* fix it to use a mock instead, so it can be in the core tests again</li>
* <li>If the test is just being lazy, and does not really need templating to test
* something, clean it up!</li>
* </ul>
*/
/* List of renames that took place:
renamed: core/src/test/java/org/elasticsearch/index/query/TemplateQueryBuilderTests.java -> modules/lang-mustache/src/test/java/org/elasticsearch/index/query/TemplateQueryBuilderTests.java
renamed: core/src/test/java/org/elasticsearch/validate/RenderSearchTemplateIT.java -> modules/lang-mustache/src/test/java/org/elasticsearch/messy/tests/RenderSearchTemplateTests.java
renamed: core/src/test/java/org/elasticsearch/search/suggest/SuggestSearchIT.java -> modules/lang-mustache/src/test/java/org/elasticsearch/messy/tests/SuggestSearchTests.java
renamed: core/src/test/java/org/elasticsearch/index/query/TemplateQueryParserTests.java -> modules/lang-mustache/src/test/java/org/elasticsearch/messy/tests/TemplateQueryParserTests.java
renamed: core/src/test/java/org/elasticsearch/index/query/TemplateQueryIT.java -> modules/lang-mustache/src/test/java/org/elasticsearch/messy/tests/TemplateQueryTests.java
*/
package org.elasticsearch.messy.tests;

View File

@ -11,6 +11,7 @@ List projects = [
'test-framework', 'test-framework',
'modules:lang-expression', 'modules:lang-expression',
'modules:lang-groovy', 'modules:lang-groovy',
'modules:lang-mustache',
'plugins:analysis-icu', 'plugins:analysis-icu',
'plugins:analysis-kuromoji', 'plugins:analysis-kuromoji',
'plugins:analysis-phonetic', 'plugins:analysis-phonetic',

View File

@ -84,7 +84,6 @@ import org.elasticsearch.indices.mapper.MapperRegistry;
import org.elasticsearch.indices.query.IndicesQueriesRegistry; import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.script.*; import org.elasticsearch.script.*;
import org.elasticsearch.script.Script.ScriptParseException; import org.elasticsearch.script.Script.ScriptParseException;
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
import org.elasticsearch.search.internal.SearchContext; import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.IndexSettingsModule; import org.elasticsearch.test.IndexSettingsModule;
@ -205,15 +204,8 @@ public abstract class AbstractQueryTestCase<QB extends AbstractQueryBuilder<QB>>
MockScriptEngine mockScriptEngine = new MockScriptEngine(); MockScriptEngine mockScriptEngine = new MockScriptEngine();
Multibinder<ScriptEngineService> multibinder = Multibinder.newSetBinder(binder(), ScriptEngineService.class); Multibinder<ScriptEngineService> multibinder = Multibinder.newSetBinder(binder(), ScriptEngineService.class);
multibinder.addBinding().toInstance(mockScriptEngine); multibinder.addBinding().toInstance(mockScriptEngine);
try {
Class.forName("com.github.mustachejava.Mustache");
} catch(ClassNotFoundException e) {
throw new IllegalStateException("error while loading mustache", e);
}
MustacheScriptEngineService mustacheScriptEngineService = new MustacheScriptEngineService(settings);
Set<ScriptEngineService> engines = new HashSet<>(); Set<ScriptEngineService> engines = new HashSet<>();
engines.add(mockScriptEngine); engines.add(mockScriptEngine);
engines.add(mustacheScriptEngineService);
List<ScriptContext.Plugin> customContexts = new ArrayList<>(); List<ScriptContext.Plugin> customContexts = new ArrayList<>();
bind(ScriptContextRegistry.class).toInstance(new ScriptContextRegistry(customContexts)); bind(ScriptContextRegistry.class).toInstance(new ScriptContextRegistry(customContexts));
try { try {