Skip to content

Commit

Permalink
Enforce Completion Context Limit
Browse files Browse the repository at this point in the history
* Enforcing a maximum number of completion contexts as reqested in #32741
* Closes #32741
  • Loading branch information
TommyWind committed Feb 10, 2019
1 parent 3bf8e24 commit 3b827ab
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ public enum MergeReason {
Setting.boolSetting("index.mapper.dynamic", INDEX_MAPPER_DYNAMIC_DEFAULT,
Property.Dynamic, Property.IndexScope, Property.Deprecated);

// Maximum allowed number of completion contexts in a mapping
public static final int COMPLETION_CONTEXTS_LIMIT = 10;

//TODO this needs to be cleaned up: _timestamp and _ttl are not supported anymore, _field_names, _seq_no, _version and _source are
//also missing, not sure if on purpose. See IndicesModule#getMetadataMappers
private static final String[] SORTED_META_FIELDS = new String[]{
Expand Down Expand Up @@ -497,6 +500,7 @@ private synchronized Map<String, DocumentMapper> internalMerge(@Nullable Documen
ContextMapping.validateContextPaths(indexSettings.getIndexVersionCreated(), fieldMappers, fieldTypes::get);

if (reason == MergeReason.MAPPING_UPDATE) {
checkCompletionContextsLimit(fieldMappers);
// this check will only be performed on the master node when there is
// a call to the update mapping API. For all other cases like
// the master node restoring mappings from disk or data nodes
Expand Down Expand Up @@ -557,6 +561,18 @@ private synchronized Map<String, DocumentMapper> internalMerge(@Nullable Documen
return results;
}

private void checkCompletionContextsLimit(List<FieldMapper> fieldMappers) {
for (FieldMapper fieldMapper : fieldMappers) {
if (CompletionFieldMapper.CONTENT_TYPE.equals(fieldMapper.typeName())) {
CompletionFieldMapper.CompletionFieldType fieldType = ((CompletionFieldMapper) fieldMapper).fieldType();
if (fieldType.hasContextMappings() && fieldType.getContextMappings().size() > COMPLETION_CONTEXTS_LIMIT) {
throw new IllegalArgumentException("Limit of contexts [" + COMPLETION_CONTEXTS_LIMIT + "] in index ["
+ index().getName() + "] has been exceeded");
}
}
}
}

private boolean assertMappersShareSameFieldType() {
if (mapper != null) {
List<FieldMapper> fieldMappers = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,4 +323,25 @@ public void testDefaultMappingIsRejectedOn7() throws IOException {
+ " that indices can have at most one type.", e.getMessage());
}

public void testLimitOfContextMappings() throws Throwable {
final String index = "test";
XContentBuilder mappingBuilder = XContentFactory.jsonBuilder().startObject().startObject("properties")
.startObject("suggest").field("type", "completion").startArray("contexts");
for (int i = 0; i < MapperService.COMPLETION_CONTEXTS_LIMIT + 1; i++) {
mappingBuilder.startObject();
mappingBuilder.field("name", Integer.toString(i));
mappingBuilder.field("type", "category");
mappingBuilder.endObject();
}

mappingBuilder.endArray().endObject().endObject().endObject();
String mappings = Strings.toString(mappingBuilder);

IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> {
createIndex(index).mapperService().merge("type1", new CompressedXContent(mappings), MergeReason.MAPPING_UPDATE);
});
assertTrue(e.getMessage(),
e.getMessage().contains("Limit of contexts [" + MapperService.COMPLETION_CONTEXTS_LIMIT +
"] in index [" + index + "] has been exceeded"));
}
}

0 comments on commit 3b827ab

Please sign in to comment.