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

Disallow changing 'enabled' on the root mapper. #54463

Merged
merged 2 commits into from
Apr 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -465,9 +465,12 @@ protected void doMerge(final ObjectMapper mergeWith) {
this.dynamic = mergeWith.dynamic;
}

if (isEnabled() != mergeWith.isEnabled()) {
throw new MapperException("The [enabled] parameter can't be updated for the object mapping [" + name() + "].");
}

for (Mapper mergeWithMapper : mergeWith) {
Mapper mergeIntoMapper = mappers.get(mergeWithMapper.simpleName());
checkEnabledFieldChange(mergeWith, mergeWithMapper, mergeIntoMapper);

Mapper merged;
if (mergeIntoMapper == null) {
Expand All @@ -481,18 +484,6 @@ protected void doMerge(final ObjectMapper mergeWith) {
}
}

private static void checkEnabledFieldChange(ObjectMapper mergeWith, Mapper mergeWithMapper, Mapper mergeIntoMapper) {
if (mergeIntoMapper instanceof ObjectMapper && mergeWithMapper instanceof ObjectMapper) {
final ObjectMapper mergeIntoObjectMapper = (ObjectMapper) mergeIntoMapper;
final ObjectMapper mergeWithObjectMapper = (ObjectMapper) mergeWithMapper;

if (mergeIntoObjectMapper.isEnabled() != mergeWithObjectMapper.isEnabled()) {
final String path = mergeWith.fullPath() + "." + mergeWithObjectMapper.simpleName() + ".enabled";
throw new MapperException("Can't update attribute for type [" + path + "] in index mapping");
}
}
}

@Override
public ObjectMapper updateFieldType(Map<String, MappedFieldType> fullNameToFieldType) {
List<Mapper> updatedMappers = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public void testMergeWhenDisablingField() {
// WHEN merging mappings
// THEN a MapperException is thrown with an excepted message
MapperException e = expectThrows(MapperException.class, () -> rootObjectMapper.merge(mergeWith));
assertEquals("Can't update attribute for type [type1.foo.enabled] in index mapping", e.getMessage());
assertEquals("The [enabled] parameter can't be updated for the object mapping [foo].", e.getMessage());
}

public void testMergeWhenEnablingField() {
Expand All @@ -93,7 +93,16 @@ public void testMergeWhenEnablingField() {
// WHEN merging mappings
// THEN a MapperException is thrown with an excepted message
MapperException e = expectThrows(MapperException.class, () -> rootObjectMapper.merge(mergeWith));
assertEquals("Can't update attribute for type [type1.disabled.enabled] in index mapping", e.getMessage());
assertEquals("The [enabled] parameter can't be updated for the object mapping [disabled].", e.getMessage());
}

public void testDisableRootMapper() {
String type = MapperService.SINGLE_MAPPING_NAME;
ObjectMapper firstMapper = createRootObjectMapper(type, true, Collections.emptyMap());
ObjectMapper secondMapper = createRootObjectMapper(type, false, Collections.emptyMap());

MapperException e = expectThrows(MapperException.class, () -> firstMapper.merge(secondMapper));
assertEquals("The [enabled] parameter can't be updated for the object mapping [" + type + "].", e.getMessage());
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's pretty confusing that this error message will contain the singleton type name: "The [enabled] parameter can't be updated for the object mapping [_doc]." I think we should address this in a separate, more general change to not pass in the type as the root object mapper's name.

}

private static RootObjectMapper createRootObjectMapper(String name, boolean enabled, Map<String, Mapper> mappers) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
import org.elasticsearch.index.engine.EngineException;
import org.elasticsearch.index.engine.InternalEngineFactory;
import org.elasticsearch.index.fieldvisitor.FieldsVisitor;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.SeqNoFieldMapper;
import org.elasticsearch.index.mapper.SourceToParse;
import org.elasticsearch.index.mapper.Uid;
Expand Down Expand Up @@ -236,7 +235,6 @@ public void testRestoreMinmal() throws IOException {
IndexMetadata metadata = runAsSnapshot(threadPool, () -> repository.getSnapshotIndexMetadata(snapshotId, indexId));
IndexShard restoredShard = newShard(
shardRouting, metadata, null, SourceOnlySnapshotRepository.getEngineFactory(), () -> {}, RetentionLeaseSyncer.EMPTY);
restoredShard.mapperService().merge(shard.indexSettings().getIndexMetadata(), MapperService.MergeReason.MAPPING_RECOVERY);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll double check with someone from the distributed team that this change is okay.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@original-brownbear would you be up for taking a look? I saw that you made several changes in this area recently.

Copy link
Member

Choose a reason for hiding this comment

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

I think this is fine. This line seems unnecessary and makes the test behave less like a real restore as far as I can see anyway (just restoring the meta from the repo in a real restore).
=> LGTM :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @original-brownbear ! It also seemed strange to me, that we would add the original mappings as part of restoring a source-only snapshot.

DiscoveryNode discoveryNode = new DiscoveryNode("node_g", buildNewFakeTransportAddress(), Version.CURRENT);
restoredShard.markAsRecovering("test from snap", new RecoveryState(restoredShard.routingEntry(), discoveryNode, null));
runAsSnapshot(shard.getThreadPool(), () -> {
Expand Down