Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add validation for dynamic templates #51233

Merged
merged 10 commits into from
Feb 27, 2020

Conversation

martijnvg
Copy link
Member

@martijnvg martijnvg commented Jan 20, 2020

Today misconfiguration of dynamic templates are discovered when indexing a document with an unmapped field. With this change the misconfiguration will be known when creating an index.

The validation logic tries to load a Mapper instance for the mapping snippet of a dynamic template. This should catch things like using an analyzer that is undefined or mapping attributes that are unused.

This is best effort:

  • If {{name}} placeholder is used in the mapping snippet then validation is skipped.
  • If match_mapping_type is not specified then validation is performed for all mapping types. If parsing succeeds with a single mapping type then this the dynamic mapping is considered valid.

If is detected that a dynamic template mapping snippet is invalid at mapping update time then the mapping update is failed for indices created on 8.0.0-alpha1 and later. For indices created
on prior version a deprecation warning is emitted instead. In 7.x clusters the mapping update
will never fail in case of an invalid dynamic template mapping snippet and a deprecation warning will always be omitted.

Closes #17411
Closes #24419

@martijnvg martijnvg added WIP :Search Foundations/Mapping Index mappings, including merging and defining field types :Data Management/Indices APIs APIs to create and manage indices and templates labels Jan 20, 2020
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-search (:Search/Mapping)

@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-features (:Core/Features/Indices APIs)

Copy link
Contributor

@jpountz jpountz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left some quick comments but the approach looks sensible to me.

private static void validateDynamicTemplate(Mapper.TypeParser.ParserContext parserContext,
DynamicTemplate dynamicTemplate) {

if (containsSnippet(dynamicTemplate.getMapping(), "{name}")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to check {dynamic_type} too?

Copy link
Member Author

@martijnvg martijnvg Feb 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only {name}, because if the type hasn't specifically configured then line 360 ensures that all possible dynamic types are checked.

@@ -621,6 +621,7 @@ private static void updateIndexMappingsAndBuildSortOrder(IndexService indexServi
if (!mappings.isEmpty()) {
assert mappings.size() == 1 : mappings;
mapperService.merge(MapperService.SINGLE_MAPPING_NAME, mappings, MergeReason.MAPPING_UPDATE);
mapperService.validateDynamicTemplates();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to only validate dynamic templates at creation time, should we move validation to MapperService#merge to make sure we cover all cases, including mapping updates that add dynamic templates on existing indices?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I will address this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dynamic template are now validated when parsed by root object type parser.
I think this has the same effect?

Tries to load a `Mapper.Builder` instance for the mapping snippet of a dynamic template.
This should catch things like using a analyzer that is undefined or mapping attributes that are unused.

This is best effort:
* If `{{name}}` placeholder is used in the mapping snippet then validation is skipped.
* If `match_mapping_type` is not specified then validation is performed for all mapping types.
  If parsing succeeds with a single mapping type then this the dynamic mapping is considered valid.

This validation can be enabled on indices created on a master node with version 8.0.0 or higher.
For 7.x a deprecation warning can be omitted instead.

Closes elastic#17411
Closes elastic#24419
…e parsed.

* Added tests and updated the documentation
@martijnvg martijnvg marked this pull request as ready for review February 14, 2020 10:57
Copy link
Contributor

@jpountz jpountz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left some minor comments but it looks good to me in general. I think that we need an important precision in the docs about the fact that we consider a template valid if there is at least one match_mapping_type that works, which means that there are still cases when we will try to create invalid mappings through dynamic templates?

docs/reference/mapping/dynamic/templates.asciidoc Outdated Show resolved Hide resolved
Map<String, Object> fieldTypeConfig = dynamicTemplate.mappingForName("__dummy__", defaultDynamicType);
fieldTypeConfig.remove("type");
try {
Mapper.Builder<?, ?> dummyBuilder = typeParser.parse("__dummy__", fieldTypeConfig, parserContext);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think some fields might do extra validation when calling builder.build(), should we try to build the mapper too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I will try to do this here.

Co-Authored-By: Adrien Grand <jpountz@gmail.com>
@martijnvg
Copy link
Member Author

Thanks for reviewing @jpountz.

I think that we need an important precision in the docs about the fact that we consider a template valid if there is at least one match_mapping_type that works, which means that there are still cases when we will try to create invalid mappings through dynamic templates?

True. I will word the docs differently to reflect this.

Copy link
Contributor

@jpountz jpountz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@martijnvg martijnvg merged commit 31b2987 into elastic:master Feb 27, 2020
martijnvg added a commit to martijnvg/elasticsearch that referenced this pull request Feb 27, 2020
Tries to load a `Mapper` instance for the mapping snippet of a dynamic template.
This should catch things like using an analyzer that is undefined or mapping attributes that are unused.

This is best effort:
* If `{{name}}` placeholder is used in the mapping snippet then validation is skipped.
* If `match_mapping_type` is not specified then validation is performed for all mapping types.
  If parsing succeeds with a single mapping type then this the dynamic mapping is considered valid.

If is detected that a dynamic template mapping snippet is invalid at mapping update time then the mapping update is failed for indices created on 8.0.0-alpha1 and later. For indices created on prior version a deprecation warning is omitted instead. In 7.x clusters the mapping update will never fail in case of an invalid dynamic template mapping snippet and a deprecation warning will always be omitted.

Closes elastic#17411
Closes elastic#24419

Co-authored-by: Adrien Grand <jpountz@gmail.com>
martijnvg added a commit that referenced this pull request Feb 28, 2020
Backport of #51233 to the seven dot x branch.

Tries to load a `Mapper` instance for the mapping snippet of a dynamic template.
This should catch things like using an analyzer that is undefined or mapping attributes that are unused.

This is best effort:
* If `{{name}}` placeholder is used in the mapping snippet then validation is skipped.
* If `match_mapping_type` is not specified then validation is performed for all mapping types.
  If parsing succeeds with a single mapping type then this the dynamic mapping is considered valid.

If is detected that a dynamic template mapping snippet is invalid at mapping update time then the mapping update is failed for indices created on 8.0.0-alpha1 and later. For indices created on prior version a deprecation warning is omitted instead. In 7.x clusters the mapping update will never fail in case of an invalid dynamic template mapping snippet and a deprecation warning will always be omitted.

Closes #17411
Closes #24419

Co-authored-by: Adrien Grand <jpountz@gmail.com>
martijnvg added a commit to martijnvg/elasticsearch that referenced this pull request Aug 10, 2020
Include the attempted 'match_mapping_type' into the message,
so that it is clearer that multiple validation attempts have occurred.

Dynamic template validation was recently added via elastic#51233 and
there was some confusion over the deprecation message itself.
(in 7.x only deprecation warning will be omitted and from 8.0
 an error will be returned)
martijnvg added a commit that referenced this pull request Nov 12, 2020
Include the attempted 'match_mapping_type' into the message,
so that it is clearer that multiple validation attempts have occurred.

Dynamic template validation was recently added via #51233 and
there was some confusion over the deprecation message itself.
(in 7.x only deprecation warning will be omitted and from 8.0
 an error will be returned)
martijnvg added a commit to martijnvg/elasticsearch that referenced this pull request Nov 12, 2020
Backporting elastic#60870 to 7.x branch.

Include the attempted 'match_mapping_type' into the message,
so that it is clearer that multiple validation attempts have occurred.

Dynamic template validation was recently added via elastic#51233 and
there was some confusion over the deprecation message itself.
(in 7.x only deprecation warning will be omitted and from 8.0
 an error will be returned)
martijnvg added a commit that referenced this pull request Nov 12, 2020
Backporting #60870 to 7.x branch.

Include the attempted 'match_mapping_type' into the message,
so that it is clearer that multiple validation attempts have occurred.

Dynamic template validation was recently added via #51233 and
there was some confusion over the deprecation message itself.
(in 7.x only deprecation warning will be omitted and from 8.0
 an error will be returned)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>breaking :Data Management/Indices APIs APIs to create and manage indices and templates >enhancement :Search Foundations/Mapping Index mappings, including merging and defining field types v7.7.0 v8.0.0-alpha1
Projects
None yet
4 participants