watcher: Add limited capability to upgrade the source of a watcher upon startup.
This particular change focuses on upgrading the source of a watch when it comes to scripts that have no language specified explicitly. The default language in version 5 changed to painless from whatever is specified in `script.default_lang` setting (this defaulted to groovy). In order to make sure that scripts in watcher remain to work we should rewrite the search source upon startup and set the legacy default language explicitly. The legacy script language is now controlled by `script.legacy.default_lang` setting and that defaults to groovy. Changing the source upon startup should do the trick and only change the source of watches with scripts that don't have an explicit language set. For new watches the default language used in scripts is painless and because we now always serialize the language explicitly in scripts these watches won't be changed on startup. The upgrade logic added here tries to upgrade scripts in the following places in a watch: * script condition * script transform * any script defined inside of a search input Original commit: elastic/x-pack-elasticsearch@4d578819eb
This commit is contained in:
parent
4bf685cd31
commit
b74f1e6cb2
|
@ -27,6 +27,8 @@ import java.util.Objects;
|
|||
*/
|
||||
public class TextTemplate implements ToXContent {
|
||||
|
||||
public static final String DEFAULT_TEMPLATE_LANG = "mustache";
|
||||
|
||||
private final Script script;
|
||||
private final String inlineTemplate;
|
||||
|
||||
|
@ -37,7 +39,7 @@ public class TextTemplate implements ToXContent {
|
|||
|
||||
public TextTemplate(String template, @Nullable XContentType contentType, ScriptType type,
|
||||
@Nullable Map<String, Object> params) {
|
||||
this.script = new Script(template, type, "mustache", params, contentType);
|
||||
this.script = new Script(template, type, DEFAULT_TEMPLATE_LANG, params, contentType);
|
||||
this.inlineTemplate = null;
|
||||
}
|
||||
|
||||
|
@ -95,7 +97,7 @@ public class TextTemplate implements ToXContent {
|
|||
if (parser.currentToken() == XContentParser.Token.VALUE_STRING) {
|
||||
return new TextTemplate(parser.text());
|
||||
} else {
|
||||
return new TextTemplate(Script.parse(parser, ParseFieldMatcher.STRICT, "mustache"));
|
||||
return new TextTemplate(Script.parse(parser, ParseFieldMatcher.STRICT, DEFAULT_TEMPLATE_LANG));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public class ActionRegistry {
|
|||
return parsers.get(type);
|
||||
}
|
||||
|
||||
public ExecutableActions parseActions(String watchId, XContentParser parser) throws IOException {
|
||||
public ExecutableActions parseActions(String watchId, XContentParser parser, boolean upgradeActionSource) throws IOException {
|
||||
if (parser.currentToken() != XContentParser.Token.START_OBJECT) {
|
||||
throw new ElasticsearchParseException("could not parse actions for watch [{}]. expected an object but found [{}] instead",
|
||||
watchId, parser.currentToken());
|
||||
|
@ -62,7 +62,8 @@ public class ActionRegistry {
|
|||
throw new ElasticsearchParseException("could not parse action [{}] for watch [{}]. {}", id, watchId, error);
|
||||
}
|
||||
} else if (token == XContentParser.Token.START_OBJECT && id != null) {
|
||||
actions.add(ActionWrapper.parse(watchId, id, parser, this, conditionRegistry, transformRegistry, clock, licenseState));
|
||||
actions.add(ActionWrapper.parse(watchId, id, parser, this, conditionRegistry, transformRegistry, clock,
|
||||
licenseState, upgradeActionSource));
|
||||
}
|
||||
}
|
||||
return new ExecutableActions(actions);
|
||||
|
|
|
@ -201,7 +201,7 @@ public class ActionWrapper implements ToXContent {
|
|||
|
||||
static ActionWrapper parse(String watchId, String actionId, XContentParser parser,
|
||||
ActionRegistry actionRegistry, ConditionRegistry conditionRegistry, TransformRegistry transformRegistry,
|
||||
Clock clock, XPackLicenseState licenseState) throws IOException {
|
||||
Clock clock, XPackLicenseState licenseState, boolean upgradeActionSource) throws IOException {
|
||||
|
||||
assert parser.currentToken() == XContentParser.Token.START_OBJECT;
|
||||
|
||||
|
@ -217,9 +217,9 @@ public class ActionWrapper implements ToXContent {
|
|||
currentFieldName = parser.currentName();
|
||||
} else {
|
||||
if (ParseFieldMatcher.STRICT.match(currentFieldName, Watch.Field.CONDITION)) {
|
||||
condition = conditionRegistry.parseExecutable(watchId, parser);
|
||||
condition = conditionRegistry.parseExecutable(watchId, parser, upgradeActionSource);
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Transform.Field.TRANSFORM)) {
|
||||
transform = transformRegistry.parse(watchId, parser);
|
||||
transform = transformRegistry.parse(watchId, parser, upgradeActionSource);
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Throttler.Field.THROTTLE_PERIOD)) {
|
||||
throttlePeriod = timeValueMillis(parser.longValue());
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Throttler.Field.THROTTLE_PERIOD_HUMAN)) {
|
||||
|
|
|
@ -28,8 +28,14 @@ public abstract class ConditionFactory<C extends Condition, R extends Condition.
|
|||
|
||||
/**
|
||||
* Parses the given xcontent and creates a concrete condition
|
||||
*
|
||||
* @param watchId The id of the watch
|
||||
* @param parser The parsing that contains the condition content
|
||||
* @param upgradeConditionSource Whether to upgrade the source related to condition if in legacy format
|
||||
* Note: depending on the version, only conditions implementations that have a
|
||||
* known legacy format will support this option, otherwise this is a noop.
|
||||
*/
|
||||
public abstract C parseCondition(String watchId, XContentParser parser) throws IOException;
|
||||
public abstract C parseCondition(String watchId, XContentParser parser, boolean upgradeConditionSource) throws IOException;
|
||||
|
||||
/**
|
||||
* Creates an {@link ExecutableCondition executable condition} for the given condition.
|
||||
|
|
|
@ -40,9 +40,15 @@ public class ConditionRegistry {
|
|||
* }
|
||||
* }
|
||||
* </code></pre>
|
||||
*
|
||||
* @param watchId The id of the watch
|
||||
* @param parser The parsing that contains the condition content
|
||||
* @param upgradeConditionSource Whether to upgrade the source related to condition if in legacy format
|
||||
* Note: depending on the version, only conditions implementations that have a
|
||||
* known legacy format will support this option, otherwise this is a noop.
|
||||
*/
|
||||
public ExecutableCondition parseExecutable(String watchId, XContentParser parser) throws IOException {
|
||||
Condition condition = parseCondition(watchId, parser);
|
||||
public ExecutableCondition parseExecutable(String watchId, XContentParser parser, boolean upgradeConditionSource) throws IOException {
|
||||
Condition condition = parseCondition(watchId, parser, upgradeConditionSource);
|
||||
return factories.get(condition.type()).createExecutable(condition);
|
||||
}
|
||||
|
||||
|
@ -56,7 +62,7 @@ public class ConditionRegistry {
|
|||
* }
|
||||
* </code></pre>
|
||||
*/
|
||||
public Condition parseCondition(String watchId, XContentParser parser) throws IOException {
|
||||
public Condition parseCondition(String watchId, XContentParser parser, boolean upgradeConditionSource) throws IOException {
|
||||
Condition condition = null;
|
||||
ConditionFactory factory = null;
|
||||
|
||||
|
@ -74,7 +80,7 @@ public class ConditionRegistry {
|
|||
throw new ElasticsearchParseException("could not parse condition for watch [{}]. unknown condition type [{}]",
|
||||
watchId, type);
|
||||
}
|
||||
condition = factory.parseCondition(watchId, parser);
|
||||
condition = factory.parseCondition(watchId, parser, upgradeConditionSource);
|
||||
}
|
||||
}
|
||||
if (condition == null) {
|
||||
|
|
|
@ -32,7 +32,7 @@ public class AlwaysConditionFactory extends ConditionFactory<AlwaysCondition, Al
|
|||
}
|
||||
|
||||
@Override
|
||||
public AlwaysCondition parseCondition(String watchId, XContentParser parser) throws IOException {
|
||||
public AlwaysCondition parseCondition(String watchId, XContentParser parser, boolean upgradeConditionSource) throws IOException {
|
||||
return AlwaysCondition.parse(watchId, parser);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ public class CompareConditionFactory extends ConditionFactory<CompareCondition,
|
|||
}
|
||||
|
||||
@Override
|
||||
public CompareCondition parseCondition(String watchId, XContentParser parser) throws IOException {
|
||||
public CompareCondition parseCondition(String watchId, XContentParser parser, boolean upgradeConditionSource) throws IOException {
|
||||
return CompareCondition.parse(watchId, parser);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public class ArrayCompareConditionFactory extends ConditionFactory<ArrayCompareC
|
|||
}
|
||||
|
||||
@Override
|
||||
public ArrayCompareCondition parseCondition(String watchId, XContentParser parser) throws IOException {
|
||||
public ArrayCompareCondition parseCondition(String watchId, XContentParser parser, boolean upgradeConditionSource) throws IOException {
|
||||
return ArrayCompareCondition.parse(watchId, parser);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ public class NeverConditionFactory extends ConditionFactory<NeverCondition, Neve
|
|||
}
|
||||
|
||||
@Override
|
||||
public NeverCondition parseCondition(String watchId, XContentParser parser) throws IOException {
|
||||
public NeverCondition parseCondition(String watchId, XContentParser parser, boolean upgradeConditionSource) throws IOException {
|
||||
return NeverCondition.parse(watchId, parser);
|
||||
}
|
||||
|
||||
|
|
|
@ -53,9 +53,15 @@ public class ScriptCondition implements Condition {
|
|||
return script.hashCode();
|
||||
}
|
||||
|
||||
public static ScriptCondition parse(String watchId, XContentParser parser) throws IOException {
|
||||
public static ScriptCondition parse(String watchId, XContentParser parser, boolean upgradeConditionSource,
|
||||
String defaultLegacyScriptLanguage) throws IOException {
|
||||
try {
|
||||
Script script = Script.parse(parser, ParseFieldMatcher.STRICT);
|
||||
Script script;
|
||||
if (upgradeConditionSource) {
|
||||
script = Script.parse(parser, ParseFieldMatcher.STRICT, defaultLegacyScriptLanguage);
|
||||
} else {
|
||||
script = Script.parse(parser, ParseFieldMatcher.STRICT);
|
||||
}
|
||||
return new ScriptCondition(script);
|
||||
} catch (ElasticsearchParseException pe) {
|
||||
throw new ElasticsearchParseException("could not parse [{}] condition for watch [{}]. failed to parse script", pe, TYPE,
|
||||
|
|
|
@ -10,20 +10,20 @@ import org.elasticsearch.common.logging.Loggers;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.xpack.watcher.condition.ConditionFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ScriptConditionFactory extends ConditionFactory<ScriptCondition, ScriptCondition.Result, ExecutableScriptCondition> {
|
||||
|
||||
private final Settings settings;
|
||||
private final ScriptService scriptService;
|
||||
|
||||
@Inject
|
||||
public ScriptConditionFactory(Settings settings, ScriptService service) {
|
||||
super(Loggers.getLogger(ExecutableScriptCondition.class, settings));
|
||||
this.settings = settings;
|
||||
scriptService = service;
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,9 @@ public class ScriptConditionFactory extends ConditionFactory<ScriptCondition, Sc
|
|||
}
|
||||
|
||||
@Override
|
||||
public ScriptCondition parseCondition(String watchId, XContentParser parser) throws IOException {
|
||||
return ScriptCondition.parse(watchId, parser);
|
||||
public ScriptCondition parseCondition(String watchId, XContentParser parser, boolean upgradeConditionSource) throws IOException {
|
||||
String defaultLegacyScriptLanguage = ScriptSettings.getLegacyDefaultLang(settings);
|
||||
return ScriptCondition.parse(watchId, parser, upgradeConditionSource, defaultLegacyScriptLanguage);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,16 +28,22 @@ public abstract class InputFactory<I extends Input, R extends Input.Result, E ex
|
|||
|
||||
/**
|
||||
* Parses the given xcontent and creates a concrete input
|
||||
*
|
||||
* @param watchId The id of the watch
|
||||
* @param parser The parser containing the input content of the watch
|
||||
* @param upgradeInputSource Whether to upgrade the source related to the inpit if that source is in legacy format
|
||||
* Note: depending on the version, only input implementations that have a known legacy
|
||||
* format will support this option, otherwise this is a noop.
|
||||
*/
|
||||
public abstract I parseInput(String watchId, XContentParser parser) throws IOException;
|
||||
public abstract I parseInput(String watchId, XContentParser parser, boolean upgradeInputSource) throws IOException;
|
||||
|
||||
/**
|
||||
* Creates an executable input out of the given input.
|
||||
*/
|
||||
public abstract E createExecutable(I input);
|
||||
|
||||
public E parseExecutable(String watchId, XContentParser parser) throws IOException {
|
||||
I input = parseInput(watchId, parser);
|
||||
public E parseExecutable(String watchId, XContentParser parser, boolean upgradeInputSource) throws IOException {
|
||||
I input = parseInput(watchId, parser, upgradeInputSource);
|
||||
return createExecutable(input);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,17 @@ public class InputRegistry {
|
|||
* @return A new input instance from the parser
|
||||
*/
|
||||
public ExecutableInput parse(String watchId, XContentParser parser) throws IOException {
|
||||
return parse(watchId, parser, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of parser to create the correct Input
|
||||
*
|
||||
* @param parser The parser containing the input definition
|
||||
* @param upgradeInputSource Whether to upgrade the source related to input if in legacy format.
|
||||
* @return A new input instance from the parser
|
||||
*/
|
||||
public ExecutableInput parse(String watchId, XContentParser parser, boolean upgradeInputSource) throws IOException {
|
||||
String type = null;
|
||||
|
||||
if (parser.currentToken() != XContentParser.Token.START_OBJECT) {
|
||||
|
@ -55,7 +66,7 @@ public class InputRegistry {
|
|||
if (factory == null) {
|
||||
throw new ElasticsearchParseException("could not parse input for watch [{}]. unknown input type [{}]", watchId, type);
|
||||
}
|
||||
input = factory.parseExecutable(watchId, parser);
|
||||
input = factory.parseExecutable(watchId, parser, upgradeInputSource);
|
||||
} else {
|
||||
throw new ElasticsearchParseException("could not parse input for watch [{}]. expected an object representing input [{}], " +
|
||||
"but found [{}] instead", watchId, type, token);
|
||||
|
|
|
@ -7,7 +7,6 @@ package org.elasticsearch.xpack.watcher.input.chain;
|
|||
|
||||
import org.elasticsearch.common.collect.Tuple;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.Injector;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
@ -36,7 +35,7 @@ public class ChainInputFactory extends InputFactory<ChainInput, ChainInput.Resul
|
|||
}
|
||||
|
||||
@Override
|
||||
public ChainInput parseInput(String watchId, XContentParser parser) throws IOException {
|
||||
public ChainInput parseInput(String watchId, XContentParser parser, boolean upgradeInputSource) throws IOException {
|
||||
return ChainInput.parse(watchId, parser, inputRegistry);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ public final class HttpInputFactory extends InputFactory<HttpInput, HttpInput.Re
|
|||
}
|
||||
|
||||
@Override
|
||||
public HttpInput parseInput(String watchId, XContentParser parser) throws IOException {
|
||||
public HttpInput parseInput(String watchId, XContentParser parser, boolean upgradeInputSource) throws IOException {
|
||||
return HttpInput.parse(watchId, parser, requestTemplateParser);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ public class NoneInputFactory extends InputFactory<NoneInput, NoneInput.Result,
|
|||
}
|
||||
|
||||
@Override
|
||||
public NoneInput parseInput(String watchId, XContentParser parser) throws IOException {
|
||||
public NoneInput parseInput(String watchId, XContentParser parser, boolean upgradeInputSource) throws IOException {
|
||||
return NoneInput.parse(watchId, parser);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.watcher.input.search;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
|
@ -12,9 +13,7 @@ import org.elasticsearch.common.ParseFieldMatcher;
|
|||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.search.aggregations.AggregatorParsers;
|
||||
import org.elasticsearch.search.suggest.Suggesters;
|
||||
import org.elasticsearch.search.SearchRequestParsers;
|
||||
import org.elasticsearch.xpack.watcher.input.Input;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherDateTimeUtils;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateRequest;
|
||||
|
@ -109,9 +108,11 @@ public class SearchInput implements Input {
|
|||
return builder;
|
||||
}
|
||||
|
||||
public static SearchInput parse(String watchId, XContentParser parser, QueryParseContext context,
|
||||
AggregatorParsers aggParsers, Suggesters suggesters)
|
||||
throws IOException {
|
||||
public static SearchInput parse(Logger inputLogger, String watchId, XContentParser parser,
|
||||
boolean upgradeInputSource,
|
||||
String defaultLegacyScriptLanguage,
|
||||
ParseFieldMatcher parseFieldMatcher,
|
||||
SearchRequestParsers searchRequestParsers) throws IOException {
|
||||
WatcherSearchTemplateRequest request = null;
|
||||
Set<String> extract = null;
|
||||
TimeValue timeout = null;
|
||||
|
@ -124,7 +125,8 @@ public class SearchInput implements Input {
|
|||
currentFieldName = parser.currentName();
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.REQUEST)) {
|
||||
try {
|
||||
request = WatcherSearchTemplateRequest.fromXContent(parser, ExecutableSearchInput.DEFAULT_SEARCH_TYPE);
|
||||
request = WatcherSearchTemplateRequest.fromXContent(inputLogger, parser, ExecutableSearchInput.DEFAULT_SEARCH_TYPE,
|
||||
upgradeInputSource, defaultLegacyScriptLanguage, parseFieldMatcher, searchRequestParsers);
|
||||
} catch (ElasticsearchParseException srpe) {
|
||||
throw new ElasticsearchParseException("could not parse [{}] input for watch [{}]. failed to parse [{}]", srpe, TYPE,
|
||||
watchId, currentFieldName);
|
||||
|
|
|
@ -11,12 +11,9 @@ import org.elasticsearch.common.logging.Loggers;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.search.SearchRequestParsers;
|
||||
import org.elasticsearch.search.aggregations.AggregatorParsers;
|
||||
import org.elasticsearch.search.suggest.Suggesters;
|
||||
import org.elasticsearch.xpack.security.InternalClient;
|
||||
import org.elasticsearch.xpack.watcher.input.InputFactory;
|
||||
import org.elasticsearch.xpack.watcher.input.simple.ExecutableSimpleInput;
|
||||
|
@ -25,11 +22,9 @@ import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateServi
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SearchInputFactory extends InputFactory<SearchInput, SearchInput.Result, ExecutableSearchInput> {
|
||||
|
||||
private final Settings settings;
|
||||
private final WatcherClientProxy client;
|
||||
private final TimeValue defaultTimeout;
|
||||
private final SearchRequestParsers searchRequestParsers;
|
||||
|
@ -45,6 +40,7 @@ public class SearchInputFactory extends InputFactory<SearchInput, SearchInput.Re
|
|||
public SearchInputFactory(Settings settings, WatcherClientProxy client,
|
||||
SearchRequestParsers searchRequestParsers, ScriptService scriptService) {
|
||||
super(Loggers.getLogger(ExecutableSimpleInput.class, settings));
|
||||
this.settings = settings;
|
||||
this.parseFieldMatcher = new ParseFieldMatcher(settings);
|
||||
this.client = client;
|
||||
this.searchRequestParsers = searchRequestParsers;
|
||||
|
@ -58,9 +54,10 @@ public class SearchInputFactory extends InputFactory<SearchInput, SearchInput.Re
|
|||
}
|
||||
|
||||
@Override
|
||||
public SearchInput parseInput(String watchId, XContentParser parser) throws IOException {
|
||||
QueryParseContext context = new QueryParseContext(searchRequestParsers.queryParsers, parser, parseFieldMatcher);
|
||||
return SearchInput.parse(watchId, parser, context, searchRequestParsers.aggParsers, searchRequestParsers.suggesters);
|
||||
public SearchInput parseInput(String watchId, XContentParser parser, boolean upgradeInputSource) throws IOException {
|
||||
String defaultLegacyScriptLanguage = ScriptSettings.getLegacyDefaultLang(settings);
|
||||
return SearchInput.parse(inputLogger, watchId, parser, upgradeInputSource, defaultLegacyScriptLanguage,
|
||||
parseFieldMatcher, searchRequestParsers);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,7 +29,7 @@ public class SimpleInputFactory extends InputFactory<SimpleInput, SimpleInput.Re
|
|||
}
|
||||
|
||||
@Override
|
||||
public SimpleInput parseInput(String watchId, XContentParser parser) throws IOException {
|
||||
public SimpleInput parseInput(String watchId, XContentParser parser, boolean upgradeInputSource) throws IOException {
|
||||
return SimpleInput.parse(watchId, parser);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.watcher.support.search;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.action.search.SearchType;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
|
@ -15,9 +16,14 @@ import org.elasticsearch.common.Strings;
|
|||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.search.SearchRequestParsers;
|
||||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.xpack.common.text.TextTemplate;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -32,8 +38,6 @@ import java.util.Objects;
|
|||
*/
|
||||
public class WatcherSearchTemplateRequest implements ToXContent {
|
||||
|
||||
private static final String DEFAULT_LANG = "mustache";
|
||||
|
||||
private final String[] indices;
|
||||
private final String[] types;
|
||||
private final SearchType searchType;
|
||||
|
@ -50,12 +54,13 @@ public class WatcherSearchTemplateRequest implements ToXContent {
|
|||
this.indicesOptions = indicesOptions;
|
||||
// Here we convert a watch search request body into an inline search template,
|
||||
// this way if any Watcher related context variables are used, they will get resolved.
|
||||
this.template = new Script(searchSource.utf8ToString(), ScriptService.ScriptType.INLINE, DEFAULT_LANG, null);
|
||||
this.template = new Script(searchSource.utf8ToString(), ScriptService.ScriptType.INLINE, TextTemplate.DEFAULT_TEMPLATE_LANG, null);
|
||||
this.searchSource = null;
|
||||
}
|
||||
|
||||
public WatcherSearchTemplateRequest(String[] indices, String[] types, SearchType searchType, IndicesOptions indicesOptions,
|
||||
Script template) {
|
||||
assert template == null || TextTemplate.DEFAULT_TEMPLATE_LANG.equals(template.getLang());
|
||||
this.indices = indices;
|
||||
this.types = types;
|
||||
this.searchType = searchType;
|
||||
|
@ -113,7 +118,7 @@ public class WatcherSearchTemplateRequest implements ToXContent {
|
|||
if (template != null) {
|
||||
return template;
|
||||
} else {
|
||||
return new Script(searchSource.utf8ToString(), ScriptService.ScriptType.INLINE, DEFAULT_LANG, null);
|
||||
return new Script(searchSource.utf8ToString(), ScriptService.ScriptType.INLINE, TextTemplate.DEFAULT_TEMPLATE_LANG, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,8 +164,12 @@ public class WatcherSearchTemplateRequest implements ToXContent {
|
|||
/**
|
||||
* Reads a new watcher search request instance for the specified parser.
|
||||
*/
|
||||
public static WatcherSearchTemplateRequest fromXContent(XContentParser parser, SearchType searchType)
|
||||
throws IOException {
|
||||
public static WatcherSearchTemplateRequest fromXContent(Logger logger, XContentParser parser,
|
||||
SearchType searchType,
|
||||
boolean upgradeSearchSource,
|
||||
String defaultLegacyScriptLanguage,
|
||||
ParseFieldMatcher parseFieldMatcher,
|
||||
SearchRequestParsers searchRequestParsers) throws IOException {
|
||||
List<String> indices = new ArrayList<>();
|
||||
List<String> types = new ArrayList<>();
|
||||
IndicesOptions indicesOptions = DEFAULT_INDICES_OPTIONS;
|
||||
|
@ -200,6 +209,19 @@ public class WatcherSearchTemplateRequest implements ToXContent {
|
|||
try (XContentBuilder builder = XContentBuilder.builder(parser.contentType().xContent())) {
|
||||
builder.copyCurrentStructure(parser);
|
||||
searchSource = builder.bytes();
|
||||
if (upgradeSearchSource) {
|
||||
XContentParser searchSourceParser = XContentHelper.createParser(searchSource);
|
||||
QueryParseContext context = new QueryParseContext(defaultLegacyScriptLanguage,
|
||||
searchRequestParsers.queryParsers, searchSourceParser, parseFieldMatcher);
|
||||
try (XContentBuilder upgradeBuilder = XContentBuilder.builder(parser.contentType().xContent())) {
|
||||
SearchSourceBuilder sourceBuilder = SearchSourceBuilder.fromXContent(context,
|
||||
searchRequestParsers.aggParsers, searchRequestParsers.suggesters);
|
||||
upgradeBuilder.value(sourceBuilder);
|
||||
searchSource = upgradeBuilder.bytes();
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to upgrade search source: [" + searchSource.utf8ToString() + "]", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, INDICES_OPTIONS_FIELD)) {
|
||||
boolean expandOpen = DEFAULT_INDICES_OPTIONS.expandWildcardsOpen();
|
||||
|
@ -248,7 +270,7 @@ public class WatcherSearchTemplateRequest implements ToXContent {
|
|||
indicesOptions = IndicesOptions.fromOptions(ignoreUnavailable, allowNoIndices, expandOpen, expandClosed,
|
||||
DEFAULT_INDICES_OPTIONS);
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, TEMPLATE_FIELD)) {
|
||||
template = Script.parse(parser, ParseFieldMatcher.STRICT, DEFAULT_LANG);
|
||||
template = Script.parse(parser, ParseFieldMatcher.STRICT, TextTemplate.DEFAULT_TEMPLATE_LANG);
|
||||
} else {
|
||||
throw new ElasticsearchParseException("could not read search request. unexpected object field [" +
|
||||
currentFieldName + "]");
|
||||
|
|
|
@ -56,7 +56,8 @@ public class WatcherSearchTemplateService extends AbstractComponent {
|
|||
if (source.getParams() != null) {
|
||||
watcherContextParams.putAll(source.getParams());
|
||||
}
|
||||
Script template = new Script(source.getScript(), source.getType(), source.getLang(), watcherContextParams,
|
||||
// Templates are always of lang mustache:
|
||||
Script template = new Script(source.getScript(), source.getType(), "mustache", watcherContextParams,
|
||||
source.getContentType());
|
||||
CompiledScript compiledScript = scriptService.compile(template, Watcher.SCRIPT_CONTEXT, Collections.emptyMap());
|
||||
return (BytesReference) scriptService.executable(compiledScript, template.getParams()).run();
|
||||
|
|
|
@ -28,16 +28,22 @@ public abstract class TransformFactory<T extends Transform, R extends Transform.
|
|||
|
||||
/**
|
||||
* Parses the given xcontent and creates a concrete transform
|
||||
*
|
||||
* @param watchId The id of the watch
|
||||
* @param parser The parsing that contains the condition content
|
||||
* @param upgradeTransformSource Whether to upgrade the source related to transform if in legacy format
|
||||
* Note: depending on the version, only transform implementations that have a
|
||||
* known legacy format will support this option, otherwise this is a noop.
|
||||
*/
|
||||
public abstract T parseTransform(String watchId, XContentParser parser) throws IOException;
|
||||
public abstract T parseTransform(String watchId, XContentParser parser, boolean upgradeTransformSource) throws IOException;
|
||||
|
||||
/**
|
||||
* Creates an executable transform out of the given transform.
|
||||
*/
|
||||
public abstract E createExecutable(T transform);
|
||||
|
||||
public E parseExecutable(String watchId, XContentParser parser) throws IOException {
|
||||
T transform = parseTransform(watchId, parser);
|
||||
public E parseExecutable(String watchId, XContentParser parser, boolean upgradeTransformSource) throws IOException {
|
||||
T transform = parseTransform(watchId, parser, upgradeTransformSource);
|
||||
return createExecutable(transform);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ public class TransformRegistry {
|
|||
return factories.get(type);
|
||||
}
|
||||
|
||||
public ExecutableTransform parse(String watchId, XContentParser parser) throws IOException {
|
||||
public ExecutableTransform parse(String watchId, XContentParser parser, boolean upgradeTransformSource) throws IOException {
|
||||
String type = null;
|
||||
XContentParser.Token token;
|
||||
ExecutableTransform transform = null;
|
||||
|
@ -43,25 +43,26 @@ public class TransformRegistry {
|
|||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
type = parser.currentName();
|
||||
} else if (type != null) {
|
||||
transform = parse(watchId, type, parser);
|
||||
transform = parse(watchId, type, parser, upgradeTransformSource);
|
||||
}
|
||||
}
|
||||
return transform;
|
||||
}
|
||||
|
||||
public ExecutableTransform parse(String watchId, String type, XContentParser parser) throws IOException {
|
||||
public ExecutableTransform parse(String watchId, String type, XContentParser parser,
|
||||
boolean upgradeTransformSource) throws IOException {
|
||||
TransformFactory factory = factories.get(type);
|
||||
if (factory == null) {
|
||||
throw new ElasticsearchParseException("could not parse transform for watch [{}], unknown transform type [{}]", watchId, type);
|
||||
}
|
||||
return factory.parseExecutable(watchId, parser);
|
||||
return factory.parseExecutable(watchId, parser, upgradeTransformSource);
|
||||
}
|
||||
|
||||
public Transform parseTransform(String watchId, String type, XContentParser parser) throws IOException {
|
||||
public Transform parseTransform(String watchId, String type, XContentParser parser, boolean upgradeSource) throws IOException {
|
||||
TransformFactory factory = factories.get(type);
|
||||
if (factory == null) {
|
||||
throw new ElasticsearchParseException("could not parse transform for watch [{}], unknown transform type [{}]", watchId, type);
|
||||
}
|
||||
return factory.parseTransform(watchId, parser);
|
||||
return factory.parseTransform(watchId, parser, upgradeSource);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,8 @@ public class ChainTransform implements Transform {
|
|||
return builder.endArray();
|
||||
}
|
||||
|
||||
public static ChainTransform parse(String watchId, XContentParser parser, TransformRegistry transformRegistry) throws IOException {
|
||||
public static ChainTransform parse(String watchId, XContentParser parser, TransformRegistry transformRegistry,
|
||||
boolean upgradeSource) throws IOException {
|
||||
XContentParser.Token token = parser.currentToken();
|
||||
if (token != XContentParser.Token.START_ARRAY) {
|
||||
throw new ElasticsearchParseException("could not parse [{}] transform for watch [{}]. expected an array of transform objects," +
|
||||
|
@ -90,7 +91,7 @@ public class ChainTransform implements Transform {
|
|||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else {
|
||||
transforms.add(transformRegistry.parseTransform(watchId, currentFieldName, parser));
|
||||
transforms.add(transformRegistry.parseTransform(watchId, currentFieldName, parser, upgradeSource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ public final class ChainTransformFactory extends TransformFactory<ChainTransform
|
|||
}
|
||||
|
||||
@Override
|
||||
public ChainTransform parseTransform(String watchId, XContentParser parser) throws IOException {
|
||||
return ChainTransform.parse(watchId, parser, registry);
|
||||
public ChainTransform parseTransform(String watchId, XContentParser parser, boolean upgradeTransformSource) throws IOException {
|
||||
return ChainTransform.parse(watchId, parser, registry, upgradeTransformSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -54,9 +54,15 @@ public class ScriptTransform implements Transform {
|
|||
return script.toXContent(builder, params);
|
||||
}
|
||||
|
||||
public static ScriptTransform parse(String watchId, XContentParser parser) throws IOException {
|
||||
public static ScriptTransform parse(String watchId, XContentParser parser, boolean upgradeSource,
|
||||
String defaultLegacyScriptLanguage) throws IOException {
|
||||
try {
|
||||
Script script = Script.parse(parser, ParseFieldMatcher.STRICT);
|
||||
Script script;
|
||||
if (upgradeSource) {
|
||||
script = Script.parse(parser, ParseFieldMatcher.STRICT, defaultLegacyScriptLanguage);
|
||||
} else {
|
||||
script = Script.parse(parser, ParseFieldMatcher.STRICT);
|
||||
}
|
||||
return new ScriptTransform(script);
|
||||
} catch (ElasticsearchParseException pe) {
|
||||
throw new ElasticsearchParseException("could not parse [{}] transform for watch [{}]. failed to parse script", pe, TYPE,
|
||||
|
|
|
@ -10,20 +10,20 @@ import org.elasticsearch.common.logging.Loggers;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.xpack.watcher.transform.TransformFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class ScriptTransformFactory extends TransformFactory<ScriptTransform, ScriptTransform.Result, ExecutableScriptTransform> {
|
||||
|
||||
private final Settings settings;
|
||||
private final ScriptService scriptService;
|
||||
|
||||
@Inject
|
||||
public ScriptTransformFactory(Settings settings, ScriptService scriptService) {
|
||||
super(Loggers.getLogger(ExecutableScriptTransform.class, settings));
|
||||
this.settings = settings;
|
||||
this.scriptService = scriptService;
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,9 @@ public class ScriptTransformFactory extends TransformFactory<ScriptTransform, Sc
|
|||
}
|
||||
|
||||
@Override
|
||||
public ScriptTransform parseTransform(String watchId, XContentParser parser) throws IOException {
|
||||
return ScriptTransform.parse(watchId, parser);
|
||||
public ScriptTransform parseTransform(String watchId, XContentParser parser, boolean upgradeTransformSource) throws IOException {
|
||||
String defaultLegacyScriptLanguage = ScriptSettings.getLegacyDefaultLang(settings);
|
||||
return ScriptTransform.parse(watchId, parser, upgradeTransformSource, defaultLegacyScriptLanguage);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.watcher.transform.search;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
|
@ -12,9 +13,7 @@ import org.elasticsearch.common.ParseFieldMatcher;
|
|||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.search.aggregations.AggregatorParsers;
|
||||
import org.elasticsearch.search.suggest.Suggesters;
|
||||
import org.elasticsearch.search.SearchRequestParsers;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherDateTimeUtils;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateRequest;
|
||||
import org.elasticsearch.xpack.watcher.transform.Transform;
|
||||
|
@ -92,9 +91,12 @@ public class SearchTransform implements Transform {
|
|||
return builder;
|
||||
}
|
||||
|
||||
public static SearchTransform parse(String watchId, XContentParser parser, QueryParseContext context,
|
||||
AggregatorParsers aggParsers, Suggesters suggesters)
|
||||
throws IOException {
|
||||
public static SearchTransform parse(Logger transformLogger, String watchId,
|
||||
XContentParser parser,
|
||||
boolean upgradeTransformSource,
|
||||
String defaultLegacyScriptLanguage,
|
||||
ParseFieldMatcher parseFieldMatcher,
|
||||
SearchRequestParsers searchRequestParsers) throws IOException {
|
||||
WatcherSearchTemplateRequest request = null;
|
||||
TimeValue timeout = null;
|
||||
DateTimeZone dynamicNameTimeZone = null;
|
||||
|
@ -106,7 +108,10 @@ public class SearchTransform implements Transform {
|
|||
currentFieldName = parser.currentName();
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.REQUEST)) {
|
||||
try {
|
||||
request = WatcherSearchTemplateRequest.fromXContent(parser, ExecutableSearchTransform.DEFAULT_SEARCH_TYPE);
|
||||
request = WatcherSearchTemplateRequest.fromXContent(
|
||||
transformLogger, parser, ExecutableSearchTransform.DEFAULT_SEARCH_TYPE, upgradeTransformSource,
|
||||
defaultLegacyScriptLanguage, parseFieldMatcher, searchRequestParsers
|
||||
);
|
||||
} catch (ElasticsearchParseException srpe) {
|
||||
throw new ElasticsearchParseException("could not parse [{}] transform for watch [{}]. failed to parse [{}]", srpe,
|
||||
TYPE, watchId, currentFieldName);
|
||||
|
|
|
@ -13,19 +13,17 @@ import org.elasticsearch.common.logging.Loggers;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.query.QueryParseContext;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.search.SearchRequestParsers;
|
||||
import org.elasticsearch.xpack.security.InternalClient;
|
||||
import org.elasticsearch.xpack.watcher.support.init.proxy.WatcherClientProxy;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService;
|
||||
import org.elasticsearch.xpack.watcher.transform.TransformFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SearchTransformFactory extends TransformFactory<SearchTransform, SearchTransform.Result, ExecutableSearchTransform> {
|
||||
|
||||
private final Settings settings;
|
||||
protected final WatcherClientProxy client;
|
||||
private final TimeValue defaultTimeout;
|
||||
private final SearchRequestParsers searchRequestParsers;
|
||||
|
@ -40,6 +38,7 @@ public class SearchTransformFactory extends TransformFactory<SearchTransform, Se
|
|||
public SearchTransformFactory(Settings settings, WatcherClientProxy client,
|
||||
SearchRequestParsers searchRequestParsers, ScriptService scriptService) {
|
||||
super(Loggers.getLogger(ExecutableSearchTransform.class, settings));
|
||||
this.settings = settings;
|
||||
this.client = client;
|
||||
this.parseFieldMatcher = new ParseFieldMatcher(settings);
|
||||
this.searchRequestParsers = searchRequestParsers;
|
||||
|
@ -53,9 +52,10 @@ public class SearchTransformFactory extends TransformFactory<SearchTransform, Se
|
|||
}
|
||||
|
||||
@Override
|
||||
public SearchTransform parseTransform(String watchId, XContentParser parser) throws IOException {
|
||||
QueryParseContext context = new QueryParseContext(searchRequestParsers.queryParsers, parser, parseFieldMatcher);
|
||||
return SearchTransform.parse(watchId, parser, context, searchRequestParsers.aggParsers, searchRequestParsers.suggesters);
|
||||
public SearchTransform parseTransform(String watchId, XContentParser parser, boolean upgradeTransformSource) throws IOException {
|
||||
String defaultLegacyScriptLanguage = ScriptSettings.getLegacyDefaultLang(settings);
|
||||
return SearchTransform.parse(transformLogger, watchId, parser, upgradeTransformSource, defaultLegacyScriptLanguage,
|
||||
parseFieldMatcher, searchRequestParsers);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -236,11 +236,15 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
|||
}
|
||||
|
||||
public Watch parse(String name, boolean includeStatus, BytesReference source) throws IOException {
|
||||
return parse(name, includeStatus, false, source, clock.nowUTC());
|
||||
return parse(name, includeStatus, false, source, clock.nowUTC(), false);
|
||||
}
|
||||
|
||||
public Watch parse(String name, boolean includeStatus, BytesReference source, boolean upgradeSource) throws IOException {
|
||||
return parse(name, includeStatus, false, source, clock.nowUTC(), upgradeSource);
|
||||
}
|
||||
|
||||
public Watch parse(String name, boolean includeStatus, BytesReference source, DateTime now) throws IOException {
|
||||
return parse(name, includeStatus, false, source, now);
|
||||
return parse(name, includeStatus, false, source, now, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -256,10 +260,11 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
|||
* @see org.elasticsearch.xpack.watcher.WatcherService#putWatch(String, BytesReference, TimeValue, boolean)
|
||||
*/
|
||||
public Watch parseWithSecrets(String id, boolean includeStatus, BytesReference source, DateTime now) throws IOException {
|
||||
return parse(id, includeStatus, true, source, now);
|
||||
return parse(id, includeStatus, true, source, now, false);
|
||||
}
|
||||
|
||||
private Watch parse(String id, boolean includeStatus, boolean withSecrets, BytesReference source, DateTime now) throws IOException {
|
||||
private Watch parse(String id, boolean includeStatus, boolean withSecrets, BytesReference source, DateTime now,
|
||||
boolean upgradeSource) throws IOException {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("parsing watch [{}] ", source.utf8ToString());
|
||||
}
|
||||
|
@ -267,7 +272,7 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
|||
try {
|
||||
parser = new WatcherXContentParser(createParser(source), new HaltedClock(now), withSecrets ? cryptoService : null);
|
||||
parser.nextToken();
|
||||
return parse(id, includeStatus, parser);
|
||||
return parse(id, includeStatus, parser, upgradeSource);
|
||||
} catch (IOException ioe) {
|
||||
throw ioException("could not parse watch [{}]", ioe, id);
|
||||
} finally {
|
||||
|
@ -277,7 +282,7 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
|||
}
|
||||
}
|
||||
|
||||
public Watch parse(String id, boolean includeStatus, XContentParser parser) throws IOException {
|
||||
public Watch parse(String id, boolean includeStatus, XContentParser parser, boolean upgradeWatchSource) throws IOException {
|
||||
Trigger trigger = null;
|
||||
ExecutableInput input = defaultInput;
|
||||
ExecutableCondition condition = defaultCondition;
|
||||
|
@ -299,11 +304,11 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
|||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.TRIGGER)) {
|
||||
trigger = triggerService.parseTrigger(id, parser);
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.INPUT)) {
|
||||
input = inputRegistry.parse(id, parser);
|
||||
input = inputRegistry.parse(id, parser, upgradeWatchSource);
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.CONDITION)) {
|
||||
condition = conditionRegistry.parseExecutable(id, parser);
|
||||
condition = conditionRegistry.parseExecutable(id, parser, upgradeWatchSource);
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.TRANSFORM)) {
|
||||
transform = transformRegistry.parse(id, parser);
|
||||
transform = transformRegistry.parse(id, parser, upgradeWatchSource);
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.THROTTLE_PERIOD)) {
|
||||
throttlePeriod = timeValueMillis(parser.longValue());
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.THROTTLE_PERIOD_HUMAN)) {
|
||||
|
@ -315,7 +320,7 @@ public class Watch implements TriggerEngine.Job, ToXContent {
|
|||
pe, id, currentFieldName);
|
||||
}
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.ACTIONS)) {
|
||||
actions = actionRegistry.parseActions(id, parser);
|
||||
actions = actionRegistry.parseActions(id, parser, upgradeWatchSource);
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.METADATA)) {
|
||||
metatdata = parser.map();
|
||||
} else if (ParseFieldMatcher.STRICT.match(currentFieldName, Field.STATUS)) {
|
||||
|
|
|
@ -50,8 +50,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
|
||||
import static org.elasticsearch.xpack.watcher.support.Exceptions.illegalState;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class WatchStore extends AbstractComponent {
|
||||
|
||||
public static final String INDEX = ".watches";
|
||||
|
@ -310,7 +308,7 @@ public class WatchStore extends AbstractComponent {
|
|||
for (SearchHit hit : response.getHits()) {
|
||||
String id = hit.getId();
|
||||
try {
|
||||
Watch watch = watchParser.parse(id, true, hit.getSourceRef());
|
||||
Watch watch = watchParser.parse(id, true, hit.getSourceRef(), true);
|
||||
watch.status().version(hit.version());
|
||||
watch.version(hit.version());
|
||||
watches.put(id, watch);
|
||||
|
|
|
@ -32,7 +32,7 @@ public class AlwaysConditionTests extends ESTestCase {
|
|||
builder.endObject();
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
AlwaysCondition condition = factory.parseCondition("_id", parser);
|
||||
AlwaysCondition condition = factory.parseCondition("_id", parser, false);
|
||||
ExecutableAlwaysCondition executable = factory.createExecutable(condition);
|
||||
assertTrue(executable.execute(null).met());
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public class AlwaysConditionTests extends ESTestCase {
|
|||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
try {
|
||||
factor.parseCondition("_id", parser);
|
||||
factor.parseCondition("_id", parser, false);
|
||||
fail("expected a condition exception trying to parse an invalid condition XContent, ["
|
||||
+ AlwaysCondition.TYPE + "] condition should not parse with a body");
|
||||
} catch (ElasticsearchParseException e) {
|
||||
|
|
|
@ -177,7 +177,7 @@ public class CompareConditionTests extends ESTestCase {
|
|||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
|
||||
CompareCondition condition = factory.parseCondition("_id", parser);
|
||||
CompareCondition condition = factory.parseCondition("_id", parser, false);
|
||||
|
||||
assertThat(condition, notNullValue());
|
||||
assertThat(condition.getPath(), is("key1.key2"));
|
||||
|
@ -195,7 +195,7 @@ public class CompareConditionTests extends ESTestCase {
|
|||
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
try {
|
||||
factory.parseCondition("_id", parser);
|
||||
factory.parseCondition("_id", parser, false);
|
||||
fail("Expected ElasticsearchParseException");
|
||||
} catch (ElasticsearchParseException e) {
|
||||
assertThat(e.getMessage(), containsString("expected an object but found [null] instead"));
|
||||
|
@ -215,7 +215,7 @@ public class CompareConditionTests extends ESTestCase {
|
|||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
try {
|
||||
factory.parseCondition("_id", parser);
|
||||
factory.parseCondition("_id", parser, false);
|
||||
fail("Expected ElasticsearchParseException");
|
||||
} catch (ElasticsearchParseException e) {
|
||||
assertThat(e.getMessage(), containsString("unknown comparison operator [foobar]"));
|
||||
|
@ -236,7 +236,7 @@ public class CompareConditionTests extends ESTestCase {
|
|||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
try {
|
||||
factory.parseCondition("_id", parser);
|
||||
factory.parseCondition("_id", parser, false);
|
||||
fail("Expected ElasticsearchParseException");
|
||||
} catch (ElasticsearchParseException e) {
|
||||
assertThat(e.getMessage(), containsString("must either be a numeric, string, boolean or null value, but found ["));
|
||||
|
|
|
@ -185,7 +185,7 @@ public class ArrayCompareConditionTests extends ESTestCase {
|
|||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
|
||||
ArrayCompareCondition condition = factory.parseCondition("_id", parser);
|
||||
ArrayCompareCondition condition = factory.parseCondition("_id", parser, false);
|
||||
|
||||
assertThat(condition, notNullValue());
|
||||
assertThat(condition.getArrayPath(), is("key1.key2"));
|
||||
|
@ -221,7 +221,7 @@ public class ArrayCompareConditionTests extends ESTestCase {
|
|||
expectedException.expect(ElasticsearchParseException.class);
|
||||
expectedException.expectMessage("duplicate comparison operator");
|
||||
|
||||
factory.parseCondition("_id", parser);
|
||||
factory.parseCondition("_id", parser, false);
|
||||
}
|
||||
|
||||
public void testParseContainsUnknownOperator() throws IOException {
|
||||
|
@ -245,7 +245,7 @@ public class ArrayCompareConditionTests extends ESTestCase {
|
|||
expectedException.expect(ElasticsearchParseException.class);
|
||||
expectedException.expectMessage("unknown comparison operator");
|
||||
|
||||
factory.parseCondition("_id", parser);
|
||||
factory.parseCondition("_id", parser, false);
|
||||
}
|
||||
|
||||
public void testParseContainsDuplicateValue() throws IOException {
|
||||
|
@ -271,7 +271,7 @@ public class ArrayCompareConditionTests extends ESTestCase {
|
|||
expectedException.expect(ElasticsearchParseException.class);
|
||||
expectedException.expectMessage("duplicate field \"value\"");
|
||||
|
||||
factory.parseCondition("_id", parser);
|
||||
factory.parseCondition("_id", parser, false);
|
||||
}
|
||||
|
||||
public void testParseContainsDuplicateQuantifier() throws IOException {
|
||||
|
@ -297,7 +297,7 @@ public class ArrayCompareConditionTests extends ESTestCase {
|
|||
expectedException.expect(ElasticsearchParseException.class);
|
||||
expectedException.expectMessage("duplicate field \"quantifier\"");
|
||||
|
||||
factory.parseCondition("_id", parser);
|
||||
factory.parseCondition("_id", parser, false);
|
||||
}
|
||||
|
||||
public void testParseContainsUnknownQuantifier() throws IOException {
|
||||
|
@ -321,7 +321,7 @@ public class ArrayCompareConditionTests extends ESTestCase {
|
|||
expectedException.expect(ElasticsearchParseException.class);
|
||||
expectedException.expectMessage("unknown comparison quantifier");
|
||||
|
||||
factory.parseCondition("_id", parser);
|
||||
factory.parseCondition("_id", parser, false);
|
||||
}
|
||||
|
||||
public void testParseContainsUnexpectedFieldInComparisonOperator() throws IOException {
|
||||
|
@ -347,6 +347,6 @@ public class ArrayCompareConditionTests extends ESTestCase {
|
|||
expectedException.expect(ElasticsearchParseException.class);
|
||||
expectedException.expectMessage("expected a field indicating the comparison value or comparison quantifier");
|
||||
|
||||
factory.parseCondition("_id", parser);
|
||||
factory.parseCondition("_id", parser, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ public class NeverConditionTests extends ESTestCase {
|
|||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
|
||||
NeverCondition condition = factory.parseCondition("_id", parser);
|
||||
NeverCondition condition = factory.parseCondition("_id", parser, false);
|
||||
ExecutableNeverCondition executable = factory.createExecutable(condition);
|
||||
assertFalse(executable.execute(null).met());
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public class NeverConditionTests extends ESTestCase {
|
|||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
try {
|
||||
factory.parseCondition("_id", parser);
|
||||
factory.parseCondition("_id", parser, false);
|
||||
fail("expected a condition exception trying to parse an invalid condition XContent, ["
|
||||
+ AlwaysCondition.TYPE + "] condition should not parse with a body");
|
||||
} catch (ElasticsearchParseException e) {
|
||||
|
|
|
@ -28,7 +28,6 @@ import org.elasticsearch.script.ScriptService.ScriptType;
|
|||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.search.internal.InternalSearchResponse;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.watch.Payload;
|
||||
|
@ -120,7 +119,7 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ScriptCondition condition = factory.parseCondition("_watch", parser);
|
||||
ScriptCondition condition = factory.parseCondition("_watch", parser, false);
|
||||
ExecutableScriptCondition executable = factory.createExecutable(condition);
|
||||
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500L, new ShardSearchFailure[0]);
|
||||
|
@ -132,7 +131,7 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
builder = createConditionContent("return true", null, ScriptType.INLINE);
|
||||
parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
condition = factory.parseCondition("_watch", parser);
|
||||
condition = factory.parseCondition("_watch", parser, false);
|
||||
executable = factory.createExecutable(condition);
|
||||
|
||||
ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
|
@ -147,7 +146,7 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
try {
|
||||
factory.parseCondition("_id", parser);
|
||||
factory.parseCondition("_id", parser, false);
|
||||
fail("expected a condition exception trying to parse an invalid condition XContent");
|
||||
} catch (ElasticsearchParseException e) {
|
||||
// TODO add these when the test if fixed
|
||||
|
@ -171,7 +170,7 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
XContentBuilder builder = createConditionContent(script, "groovy", scriptType);
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ScriptCondition scriptCondition = conditionParser.parseCondition("_watch", parser);
|
||||
ScriptCondition scriptCondition = conditionParser.parseCondition("_watch", parser, false);
|
||||
expectThrows(GeneralScriptException.class,
|
||||
() -> conditionParser.createExecutable(scriptCondition));
|
||||
}
|
||||
|
@ -182,7 +181,7 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
XContentBuilder builder = createConditionContent(script, "not_a_valid_lang", ScriptType.INLINE);
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ScriptCondition scriptCondition = conditionParser.parseCondition("_watch", parser);
|
||||
ScriptCondition scriptCondition = conditionParser.parseCondition("_watch", parser, false);
|
||||
GeneralScriptException exception = expectThrows(GeneralScriptException.class,
|
||||
() -> conditionParser.createExecutable(scriptCondition));
|
||||
assertThat(exception.getMessage(), containsString("script_lang not supported [not_a_valid_lang]]"));
|
||||
|
|
|
@ -83,7 +83,7 @@ public class ChainInputTests extends ESTestCase {
|
|||
// first pass JSON and check for correct inputs
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ChainInput chainInput = chainInputFactory.parseInput("test", parser);
|
||||
ChainInput chainInput = chainInputFactory.parseInput("test", parser, false);
|
||||
|
||||
assertThat(chainInput.getInputs(), hasSize(2));
|
||||
assertThat(chainInput.getInputs().get(0).v1(), is("first"));
|
||||
|
|
|
@ -188,7 +188,7 @@ public class HttpInputTests extends ESTestCase {
|
|||
BytesReference source = jsonBuilder().value(inputBuilder.build()).bytes();
|
||||
XContentParser parser = XContentHelper.createParser(source);
|
||||
parser.nextToken();
|
||||
HttpInput result = httpParser.parseInput("_id", parser);
|
||||
HttpInput result = httpParser.parseInput("_id", parser, false);
|
||||
|
||||
assertThat(result.type(), equalTo(HttpInput.TYPE));
|
||||
assertThat(result.getRequest().scheme(), equalTo(scheme != null ? scheme : Scheme.HTTP)); // http is the default
|
||||
|
@ -226,7 +226,7 @@ public class HttpInputTests extends ESTestCase {
|
|||
XContentParser parser = XContentHelper.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
try {
|
||||
httpParser.parseInput("_id", parser);
|
||||
httpParser.parseInput("_id", parser, false);
|
||||
fail("Expected IllegalArgumentException");
|
||||
} catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), is("unsupported http method [_METHOD]"));
|
||||
|
|
|
@ -48,7 +48,7 @@ public class SimpleInputTests extends ESTestCase {
|
|||
InputFactory parser = new SimpleInputFactory(Settings.builder().build());
|
||||
XContentParser xContentParser = JsonXContent.jsonXContent.createParser(jsonBuilder.bytes());
|
||||
xContentParser.nextToken();
|
||||
ExecutableInput input = parser.parseExecutable("_id", xContentParser);
|
||||
ExecutableInput input = parser.parseExecutable("_id", xContentParser, false);
|
||||
assertEquals(input.type(), SimpleInput.TYPE);
|
||||
|
||||
|
||||
|
@ -65,7 +65,7 @@ public class SimpleInputTests extends ESTestCase {
|
|||
XContentParser xContentParser = JsonXContent.jsonXContent.createParser(jsonBuilder.bytes());
|
||||
xContentParser.nextToken();
|
||||
try {
|
||||
parser.parseInput("_id", xContentParser);
|
||||
parser.parseInput("_id", xContentParser, false);
|
||||
fail("[simple] input parse should fail with an InputException for an empty json object");
|
||||
} catch (ElasticsearchParseException e) {
|
||||
assertThat(e.getMessage(), containsString("expected an object but found [VALUE_STRING] instead"));
|
||||
|
|
|
@ -124,7 +124,8 @@ public class WatcherUtilsTests extends ESTestCase {
|
|||
request.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
XContentParser parser = XContentHelper.createParser(builder.bytes());
|
||||
assertThat(parser.nextToken(), equalTo(XContentParser.Token.START_OBJECT));
|
||||
WatcherSearchTemplateRequest result = WatcherSearchTemplateRequest.fromXContent(parser, DEFAULT_SEARCH_TYPE);
|
||||
WatcherSearchTemplateRequest result = WatcherSearchTemplateRequest.fromXContent(logger, parser, DEFAULT_SEARCH_TYPE,
|
||||
false, null, null, null);
|
||||
|
||||
assertThat(result.getIndices(), arrayContainingInAnyOrder(expectedIndices != null ? expectedIndices : new String[0]));
|
||||
assertThat(result.getTypes(), arrayContainingInAnyOrder(expectedTypes != null ? expectedTypes : new String[0]));
|
||||
|
@ -213,7 +214,8 @@ public class WatcherUtilsTests extends ESTestCase {
|
|||
|
||||
XContentParser parser = XContentHelper.createParser(builder.bytes());
|
||||
assertThat(parser.nextToken(), equalTo(XContentParser.Token.START_OBJECT));
|
||||
WatcherSearchTemplateRequest result = WatcherSearchTemplateRequest.fromXContent(parser, DEFAULT_SEARCH_TYPE);
|
||||
WatcherSearchTemplateRequest result = WatcherSearchTemplateRequest.fromXContent(logger, parser, DEFAULT_SEARCH_TYPE,
|
||||
false, null, null, null);
|
||||
|
||||
assertThat(result.getIndices(), arrayContainingInAnyOrder(indices));
|
||||
assertThat(result.getTypes(), arrayContainingInAnyOrder(types));
|
||||
|
|
|
@ -6,15 +6,23 @@
|
|||
package org.elasticsearch.xpack.watcher.support.search;
|
||||
|
||||
import org.elasticsearch.action.search.SearchType;
|
||||
import org.elasticsearch.common.ParseFieldMatcher;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||
import org.elasticsearch.search.SearchModule;
|
||||
import org.elasticsearch.search.SearchRequestParsers;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class WatcherSearchTemplateRequestTests extends ESTestCase {
|
||||
|
@ -33,7 +41,8 @@ public class WatcherSearchTemplateRequestTests extends ESTestCase {
|
|||
try (XContentParser parser = XContentHelper.createParser(new BytesArray(source))) {
|
||||
parser.nextToken();
|
||||
|
||||
WatcherSearchTemplateRequest result = WatcherSearchTemplateRequest.fromXContent(parser, randomFrom(SearchType.values()));
|
||||
WatcherSearchTemplateRequest result = WatcherSearchTemplateRequest.fromXContent(
|
||||
logger, parser, randomFrom(SearchType.values()), false, null, null, null);
|
||||
assertNotNull(result.getTemplate());
|
||||
assertThat(result.getTemplate().getScript(), equalTo(expectedScript));
|
||||
assertThat(result.getTemplate().getLang(), equalTo(expectedLang));
|
||||
|
@ -42,4 +51,53 @@ public class WatcherSearchTemplateRequestTests extends ESTestCase {
|
|||
fail("Failed to parse watch search request: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testUpgradeSearchSource() throws IOException {
|
||||
XContentBuilder contentBuilder = jsonBuilder();
|
||||
contentBuilder.startObject();
|
||||
contentBuilder.startObject("body");
|
||||
|
||||
contentBuilder.startObject("query");
|
||||
contentBuilder.startObject("script");
|
||||
contentBuilder.startObject("script");
|
||||
contentBuilder.field("inline", "return true");
|
||||
contentBuilder.endObject();
|
||||
contentBuilder.endObject();
|
||||
contentBuilder.endObject();
|
||||
|
||||
contentBuilder.startObject("aggregations");
|
||||
contentBuilder.startObject("avg_grade");
|
||||
contentBuilder.startObject("avg");
|
||||
contentBuilder.startObject("script");
|
||||
contentBuilder.field("inline", "1 + 1");
|
||||
contentBuilder.endObject();
|
||||
contentBuilder.endObject();
|
||||
contentBuilder.endObject();
|
||||
contentBuilder.startObject("another_avg");
|
||||
contentBuilder.startObject("avg");
|
||||
contentBuilder.startObject("script");
|
||||
contentBuilder.field("inline", "1 + 2");
|
||||
contentBuilder.field("lang", "javascript");
|
||||
contentBuilder.endObject();
|
||||
contentBuilder.endObject();
|
||||
contentBuilder.endObject();
|
||||
contentBuilder.endObject();
|
||||
|
||||
contentBuilder.endObject();
|
||||
contentBuilder.endObject();
|
||||
XContentParser parser = XContentHelper.createParser(contentBuilder.bytes());
|
||||
parser.nextToken();
|
||||
|
||||
SearchRequestParsers searchRequestParsers = new SearchModule(Settings.EMPTY, false, Collections.emptyList())
|
||||
.getSearchRequestParsers();
|
||||
WatcherSearchTemplateRequest result = WatcherSearchTemplateRequest.fromXContent(
|
||||
logger, parser, SearchType.DEFAULT, true, "your_legacy_lang", ParseFieldMatcher.STRICT, searchRequestParsers);
|
||||
Map<String, Object> parsedResult = XContentHelper.convertToMap(result.getSearchSource(), true).v2();
|
||||
// after upgrading the language must be equal to legacy language, because no language was defined explicitly in these scripts:
|
||||
assertThat(XContentMapValues.extractValue("query.script.script.lang", parsedResult), equalTo("your_legacy_lang"));
|
||||
assertThat(XContentMapValues.extractValue("aggregations.avg_grade.avg.script.lang", parsedResult), equalTo("your_legacy_lang"));
|
||||
// after upgrading the language must remain javascript here, because that has been explicitly defined in the script:
|
||||
assertThat(XContentMapValues.extractValue("aggregations.another_avg.avg.script.lang", parsedResult), equalTo("javascript"));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import org.elasticsearch.search.SearchRequestParsers;
|
|||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.xpack.watcher.condition.always.ExecutableAlwaysCondition;
|
||||
import org.elasticsearch.xpack.watcher.execution.TriggeredExecutionContext;
|
||||
|
@ -152,7 +151,7 @@ public class SearchInputTests extends ESIntegTestCase {
|
|||
SearchInputFactory factory = new SearchInputFactory(Settings.EMPTY, WatcherClientProxy.of(client()),
|
||||
searchParsers, scriptService());
|
||||
|
||||
SearchInput searchInput = factory.parseInput("_id", parser);
|
||||
SearchInput searchInput = factory.parseInput("_id", parser, false);
|
||||
assertEquals(SearchInput.TYPE, searchInput.type());
|
||||
assertThat(searchInput.getTimeout(), equalTo(timeout));
|
||||
}
|
||||
|
|
|
@ -217,7 +217,7 @@ public class SearchTransformTests extends ESIntegTestCase {
|
|||
SearchRequestParsers searchRequestParsers = internalCluster().getInstance(SearchRequestParsers.class);
|
||||
SearchTransformFactory transformFactory = new SearchTransformFactory(Settings.EMPTY, WatcherClientProxy.of(client()),
|
||||
searchRequestParsers, scriptService());
|
||||
ExecutableSearchTransform executable = transformFactory.parseExecutable("_id", parser);
|
||||
ExecutableSearchTransform executable = transformFactory.parseExecutable("_id", parser, false);
|
||||
|
||||
assertThat(executable, notNullValue());
|
||||
assertThat(executable.type(), is(SearchTransform.TYPE));
|
||||
|
|
|
@ -12,6 +12,8 @@ import org.elasticsearch.action.search.SearchResponse;
|
|||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.script.MockScriptPlugin;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.xpack.watcher.support.xcontent.ObjectPath;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
|
@ -21,7 +23,10 @@ import org.elasticsearch.xpack.watcher.watch.WatchStore;
|
|||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
@ -44,6 +49,13 @@ public class WatcherBackwardsCompatibilityTests extends AbstractWatcherIntegrati
|
|||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Class<? extends Plugin>> pluginTypes() {
|
||||
List<Class<? extends Plugin>> plugins = super.pluginTypes();
|
||||
plugins.add(FoolMeScriptLang.class);
|
||||
return plugins;
|
||||
}
|
||||
|
||||
public void testWatchLoadedSuccessfullyAfterUpgrade() throws Exception {
|
||||
// setup node
|
||||
Path dataDir = createTempDir();
|
||||
|
@ -86,10 +98,32 @@ public class WatcherBackwardsCompatibilityTests extends AbstractWatcherIntegrati
|
|||
assertThat(getWatchResponse.isFound(), is(true));
|
||||
Map<String, Object> watchSourceAsMap = getWatchResponse.getSource().getAsMap();
|
||||
assertThat(ObjectPath.eval("trigger.schedule.interval", watchSourceAsMap), equalTo("99w"));
|
||||
assertThat(ObjectPath.eval("input.search.request.body.query.bool.filter.1.range.date.lte", watchSourceAsMap),
|
||||
assertThat(ObjectPath.eval("input.search.request.body.query.bool.filter.1.range.date.to", watchSourceAsMap),
|
||||
equalTo("{{ctx.trigger.scheduled_time}}"));
|
||||
assertThat(ObjectPath.eval("actions.log_error.logging.text", watchSourceAsMap),
|
||||
equalTo("Found {{ctx.payload.hits.total}} errors in the logs"));
|
||||
|
||||
// Check that all scripts have been upgraded, so that the language has been set to groovy (legacy language default):
|
||||
assertThat(ObjectPath.eval("input.search.request.body.query.bool.filter.2.script.script.lang", watchSourceAsMap),
|
||||
equalTo("groovy"));
|
||||
assertThat(ObjectPath.eval("input.search.request.body.aggregations.avg_grade.avg.script.lang", watchSourceAsMap),
|
||||
equalTo("groovy"));
|
||||
assertThat(ObjectPath.eval("condition.script.lang", watchSourceAsMap), equalTo("groovy"));
|
||||
}
|
||||
|
||||
// Fool the script service that this is the groovy script language, so that we can just load the watch upon startup
|
||||
// and verify that the lang options on scripts have been set.
|
||||
public static class FoolMeScriptLang extends MockScriptPlugin{
|
||||
|
||||
@Override
|
||||
protected Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
|
||||
return Collections.singletonMap("ctx.payload.hits.total > 0", (vars) -> true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pluginScriptLang() {
|
||||
return "groovy";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -126,7 +126,7 @@ public class ChainTransformTests extends ESTestCase {
|
|||
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ExecutableChainTransform executable = transformParser.parseExecutable("_id", parser);
|
||||
ExecutableChainTransform executable = transformParser.parseExecutable("_id", parser, false);
|
||||
assertThat(executable, notNullValue());
|
||||
assertThat(executable.transform().getTransforms(), notNullValue());
|
||||
assertThat(executable.transform().getTransforms(), hasSize(4));
|
||||
|
@ -204,7 +204,7 @@ public class ChainTransformTests extends ESTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Transform parseTransform(String watchId, XContentParser parser) throws IOException {
|
||||
public Transform parseTransform(String watchId, XContentParser parser, boolean upgradeTransformSource) throws IOException {
|
||||
if (parser.currentToken() == XContentParser.Token.VALUE_STRING) {
|
||||
return new Transform(parser.text());
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ public class ChainTransformTests extends ESTestCase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Transform parseTransform(String watchId, XContentParser parser) throws IOException {
|
||||
public Transform parseTransform(String watchId, XContentParser parser, boolean upgradeTransformSource) throws IOException {
|
||||
assert parser.currentToken() == XContentParser.Token.START_OBJECT;
|
||||
XContentParser.Token token = parser.nextToken();
|
||||
assert token == XContentParser.Token.END_OBJECT;
|
||||
|
|
|
@ -152,7 +152,7 @@ public class ScriptTransformTests extends ESTestCase {
|
|||
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ExecutableScriptTransform transform = new ScriptTransformFactory(Settings.EMPTY, service).parseExecutable("_id", parser);
|
||||
ExecutableScriptTransform transform = new ScriptTransformFactory(Settings.EMPTY, service).parseExecutable("_id", parser, false);
|
||||
Script script = new Script("_script", type, "_lang", singletonMap("key", "value"));
|
||||
assertThat(transform.transform().getScript(), equalTo(script));
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ public class ScriptTransformTests extends ESTestCase {
|
|||
|
||||
XContentParser parser = JsonXContent.jsonXContent.createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ExecutableScriptTransform transform = new ScriptTransformFactory(Settings.EMPTY, service).parseExecutable("_id", parser);
|
||||
ExecutableScriptTransform transform = new ScriptTransformFactory(Settings.EMPTY, service).parseExecutable("_id", parser, false);
|
||||
assertThat(transform.transform().getScript(), equalTo(new Script("_script")));
|
||||
}
|
||||
|
||||
|
@ -189,7 +189,7 @@ public class ScriptTransformTests extends ESTestCase {
|
|||
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ScriptTransform scriptTransform = transformFactory.parseTransform("_watch", parser);
|
||||
ScriptTransform scriptTransform = transformFactory.parseTransform("_watch", parser, false);
|
||||
try {
|
||||
transformFactory.createExecutable(scriptTransform);
|
||||
fail("expected a transform validation exception trying to create an executable with a bad or missing script");
|
||||
|
@ -212,7 +212,7 @@ public class ScriptTransformTests extends ESTestCase {
|
|||
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
parser.nextToken();
|
||||
ScriptTransform scriptCondition = transformFactory.parseTransform("_watch", parser);
|
||||
ScriptTransform scriptCondition = transformFactory.parseTransform("_watch", parser, false);
|
||||
try {
|
||||
transformFactory.createExecutable(scriptCondition);
|
||||
fail("expected a transform validation exception trying to create an executable with an invalid language");
|
||||
|
|
|
@ -67,8 +67,6 @@ import static org.mockito.Mockito.verify;
|
|||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
*/
|
||||
public class WatchStoreTests extends ESTestCase {
|
||||
private WatchStore watchStore;
|
||||
private WatcherClientProxy clientProxy;
|
||||
|
@ -221,10 +219,10 @@ public class WatchStoreTests extends ESTestCase {
|
|||
when(watch3.status()).thenReturn(status);
|
||||
Watch watch4 = mock(Watch.class);
|
||||
when(watch4.status()).thenReturn(status);
|
||||
when(parser.parse("_id1", true, source)).thenReturn(watch1);
|
||||
when(parser.parse("_id2", true, source)).thenReturn(watch2);
|
||||
when(parser.parse("_id3", true, source)).thenReturn(watch3);
|
||||
when(parser.parse("_id4", true, source)).thenReturn(watch4);
|
||||
when(parser.parse("_id1", true, source, true)).thenReturn(watch1);
|
||||
when(parser.parse("_id2", true, source, true)).thenReturn(watch2);
|
||||
when(parser.parse("_id3", true, source, true)).thenReturn(watch3);
|
||||
when(parser.parse("_id4", true, source, true)).thenReturn(watch4);
|
||||
|
||||
when(clientProxy.clearScroll(anyString())).thenReturn(new ClearScrollResponse(true, 0));
|
||||
|
||||
|
@ -303,7 +301,7 @@ public class WatchStoreTests extends ESTestCase {
|
|||
};
|
||||
when(watch.transform()).thenReturn(randomFrom(testTransform, null));
|
||||
|
||||
when(parser.parse("_id" + i, true, source)).thenReturn(watch);
|
||||
when(parser.parse("_id" + i, true, source, true)).thenReturn(watch);
|
||||
}
|
||||
|
||||
SearchResponse searchResponse = mockSearchResponse(1, 1, hitCount, hits.toArray(new InternalSearchHit[] {}));
|
||||
|
@ -365,7 +363,7 @@ public class WatchStoreTests extends ESTestCase {
|
|||
Watch watch = mock(Watch.class);
|
||||
WatchStatus status = mock(WatchStatus.class);
|
||||
when(watch.status()).thenReturn(status);
|
||||
when(parser.parse("_id1", true, source)).thenReturn(watch);
|
||||
when(parser.parse("_id1", true, source, true)).thenReturn(watch);
|
||||
|
||||
when(clientProxy.clearScroll(anyString())).thenReturn(new ClearScrollResponse(true, 0));
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ package org.elasticsearch.xpack.watcher.watch;
|
|||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.ElasticsearchParseException;
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
@ -15,10 +16,12 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.index.query.MatchAllQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryParser;
|
||||
import org.elasticsearch.index.query.ScriptQueryBuilder;
|
||||
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.script.Script;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.search.SearchRequestParsers;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.common.http.HttpClient;
|
||||
|
@ -81,6 +84,7 @@ import org.elasticsearch.xpack.watcher.input.simple.ExecutableSimpleInput;
|
|||
import org.elasticsearch.xpack.watcher.input.simple.SimpleInput;
|
||||
import org.elasticsearch.xpack.watcher.input.simple.SimpleInputFactory;
|
||||
import org.elasticsearch.xpack.watcher.support.init.proxy.WatcherClientProxy;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateRequest;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService;
|
||||
import org.elasticsearch.xpack.watcher.test.WatcherTestUtils;
|
||||
import org.elasticsearch.xpack.watcher.transform.ExecutableTransform;
|
||||
|
@ -181,7 +185,7 @@ public class WatchTests extends ESTestCase {
|
|||
TriggerService triggerService = new TriggerService(Settings.EMPTY, singleton(triggerEngine));
|
||||
|
||||
ExecutableInput input = randomInput();
|
||||
InputRegistry inputRegistry = registry(input);
|
||||
InputRegistry inputRegistry = registry(input.type());
|
||||
|
||||
ExecutableCondition condition = randomCondition();
|
||||
ConditionRegistry conditionRegistry = conditionRegistry();
|
||||
|
@ -230,7 +234,7 @@ public class WatchTests extends ESTestCase {
|
|||
TriggerService triggerService = new TriggerService(Settings.EMPTY, singleton(triggerEngine));
|
||||
ConditionRegistry conditionRegistry = conditionRegistry();
|
||||
ExecutableInput input = randomInput();
|
||||
InputRegistry inputRegistry = registry(input);
|
||||
InputRegistry inputRegistry = registry(input.type());
|
||||
|
||||
TransformRegistry transformRegistry = transformRegistry();
|
||||
|
||||
|
@ -259,7 +263,7 @@ public class WatchTests extends ESTestCase {
|
|||
TriggerService triggerService = new TriggerService(Settings.EMPTY, singleton(triggerEngine));
|
||||
|
||||
ConditionRegistry conditionRegistry = conditionRegistry();
|
||||
InputRegistry inputRegistry = registry(new ExecutableNoneInput(logger));
|
||||
InputRegistry inputRegistry = registry(new ExecutableNoneInput(logger).type());
|
||||
TransformRegistry transformRegistry = transformRegistry();
|
||||
ExecutableActions actions = new ExecutableActions(Collections.emptyList());
|
||||
ActionRegistry actionRegistry = registry(actions, conditionRegistry, transformRegistry);
|
||||
|
@ -282,6 +286,84 @@ public class WatchTests extends ESTestCase {
|
|||
assertThat(watch.actions().count(), is(0));
|
||||
}
|
||||
|
||||
public void testParseWatch_verifyScriptLangDefault() throws Exception {
|
||||
ScheduleRegistry scheduleRegistry = registry(new IntervalSchedule(new IntervalSchedule.Interval(1,
|
||||
IntervalSchedule.Interval.Unit.SECONDS)));
|
||||
TriggerEngine triggerEngine = new ParseOnlyScheduleTriggerEngine(Settings.EMPTY, scheduleRegistry, SystemClock.INSTANCE);
|
||||
TriggerService triggerService = new TriggerService(Settings.EMPTY, singleton(triggerEngine));
|
||||
|
||||
ConditionRegistry conditionRegistry = conditionRegistry();
|
||||
InputRegistry inputRegistry = registry(SearchInput.TYPE);
|
||||
TransformRegistry transformRegistry = transformRegistry();
|
||||
ExecutableActions actions = new ExecutableActions(Collections.emptyList());
|
||||
ActionRegistry actionRegistry = registry(actions, conditionRegistry, transformRegistry);
|
||||
Watch.Parser watchParser = new Watch.Parser(settings, conditionRegistry, triggerService, transformRegistry, actionRegistry,
|
||||
inputRegistry, null, SystemClock.INSTANCE);
|
||||
|
||||
IndicesQueriesRegistry queryRegistry = new IndicesQueriesRegistry();
|
||||
QueryParser<MatchAllQueryBuilder> queryParser1 = MatchAllQueryBuilder::fromXContent;
|
||||
queryRegistry.register(queryParser1, MatchAllQueryBuilder.NAME);
|
||||
QueryParser<ScriptQueryBuilder> queryParser2 = ScriptQueryBuilder::fromXContent;
|
||||
queryRegistry.register(queryParser2, ScriptQueryBuilder.NAME);
|
||||
SearchRequestParsers searchParsers = new SearchRequestParsers(queryRegistry, null, null);
|
||||
WatcherSearchTemplateService searchTemplateService = new WatcherSearchTemplateService(settings, scriptService, searchParsers);
|
||||
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
builder.startObject();
|
||||
|
||||
builder.startObject("trigger");
|
||||
builder.startObject("schedule");
|
||||
builder.field("interval", "99w");
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
|
||||
builder.startObject("input");
|
||||
builder.startObject("search");
|
||||
builder.startObject("request");
|
||||
builder.startObject("body");
|
||||
builder.startObject("query");
|
||||
builder.startObject("script");
|
||||
if (randomBoolean()) {
|
||||
builder.field("script", "return true");
|
||||
} else {
|
||||
builder.startObject("script");
|
||||
builder.field("inline", "return true");
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
builder.endObject();
|
||||
|
||||
builder.startObject("condition");
|
||||
if (randomBoolean()) {
|
||||
builder.field("script", "return true");
|
||||
} else {
|
||||
builder.startObject("script");
|
||||
builder.field("inline", "return true");
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
|
||||
builder.endObject();
|
||||
|
||||
// parse in default mode:
|
||||
Watch watch = watchParser.parse("_id", false, builder.bytes());
|
||||
assertThat(((ScriptCondition) watch.condition().condition()).getScript().getLang(), equalTo(Script.DEFAULT_SCRIPT_LANG));
|
||||
WatcherSearchTemplateRequest request = ((SearchInput) watch.input().input()).getRequest();
|
||||
SearchRequest searchRequest = searchTemplateService.toSearchRequest(request);
|
||||
assertThat(((ScriptQueryBuilder) searchRequest.source().query()).script().getLang(), equalTo(Script.DEFAULT_SCRIPT_LANG));
|
||||
|
||||
// parse in legacy mode:
|
||||
watch = watchParser.parse("_id", false, builder.bytes(), true);
|
||||
assertThat(((ScriptCondition) watch.condition().condition()).getScript().getLang(), equalTo("groovy"));
|
||||
request = ((SearchInput) watch.input().input()).getRequest();
|
||||
searchRequest = searchTemplateService.toSearchRequest(request);
|
||||
assertThat(((ScriptQueryBuilder) searchRequest.source().query()).script().getLang(), equalTo("groovy"));
|
||||
}
|
||||
|
||||
private static Schedule randomSchedule() {
|
||||
String type = randomFrom(CronSchedule.TYPE, HourlySchedule.TYPE, DailySchedule.TYPE, WeeklySchedule.TYPE, MonthlySchedule.TYPE,
|
||||
YearlySchedule.TYPE, IntervalSchedule.TYPE);
|
||||
|
@ -346,13 +428,15 @@ public class WatchTests extends ESTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
private InputRegistry registry(ExecutableInput input) {
|
||||
private InputRegistry registry(String inputType) {
|
||||
Map<String, InputFactory> parsers = new HashMap<>();
|
||||
switch (input.type()) {
|
||||
switch (inputType) {
|
||||
case SearchInput.TYPE:
|
||||
IndicesQueriesRegistry queryRegistry = new IndicesQueriesRegistry();
|
||||
QueryParser<MatchAllQueryBuilder> queryParser = MatchAllQueryBuilder::fromXContent;
|
||||
queryRegistry.register(queryParser, MatchAllQueryBuilder.NAME);
|
||||
QueryParser<MatchAllQueryBuilder> queryParser1 = MatchAllQueryBuilder::fromXContent;
|
||||
queryRegistry.register(queryParser1, MatchAllQueryBuilder.NAME);
|
||||
QueryParser<ScriptQueryBuilder> queryParser2 = ScriptQueryBuilder::fromXContent;
|
||||
queryRegistry.register(queryParser2, ScriptQueryBuilder.NAME);
|
||||
SearchRequestParsers searchParsers = new SearchRequestParsers(queryRegistry, null, null);
|
||||
parsers.put(SearchInput.TYPE, new SearchInputFactory(settings, client, searchParsers, scriptService));
|
||||
return new InputRegistry(Settings.EMPTY, parsers);
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue