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

Fix unknown camel case date-time mappings #88400

Closed
wants to merge 11 commits into from

Conversation

grcevski
Copy link
Contributor

@grcevski grcevski commented Jul 8, 2022

Elasticsearch 8.0 dropped support for camel case date time mappings, however we still support 7.x indices in 8.0. Some of these 7.x indices might've been created with camel case mappings, even though those were deprecated in 7.x, nothing stopped users from using them.

When we encounter a mapping with camel case on a 7.x index in 8.0 we mess up the cluster data, because the validation checks run way too late, after we've effectively upgraded the metadata and the directories structure.

This PR brings back the camel case compatibility for 7.x compatible indices in 8.0, the option to use a camel case index doesn't exist anymore, but we'll allow the 7.x index to work by translating the parsed field mapping.

Closes #84199

@grcevski grcevski added >bug :Core/Infra/Core Core issues without another label Team:Core/Infra Meta label for core/infra team v8.4.0 labels Jul 8, 2022
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-infra (Team:Core/Infra)

@elasticsearchmachine
Copy link
Collaborator

Hi @grcevski, I've created a changelog YAML for you.

import java.util.Map;
import java.util.stream.Collectors;

public enum LegacyFormatNames {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copied back from 7.17, with removed unnecessary methods.

Copy link
Member

@rjernst rjernst left a comment

Choose a reason for hiding this comment

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

While this fixes the immediate issue, I don't think it addresses the underlying problem: these format names exist in the mappings, which are in cluster state. So with this PR as is, a user would be able to upgrade to 8.x, and their mappings would work. But they would still show up with camelCase, and nothing would indicate to them they need to change that. Could we instead change the mappings themselves on upgrade, on the master node as we load cluster state? ie similar to other mappings upgrades we have done.

YEAR_MONTH_DAY("yearMonthDay", "year_month_day"),
EPOCH_SECOND(null, "epoch_second"),
EPOCH_MILLIS(null, "epoch_millis"),
// strict date formats here, must be at least 4 digits for year and two for months and two for day"
Copy link
Member

Choose a reason for hiding this comment

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

nit: trailing quote

this.snakeCaseName = snakeCaseName;
}

public static String compatibleFormat(String format) {
Copy link
Member

Choose a reason for hiding this comment

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

maybe use "get" terminology here? getCompatibleFormat

@pgomulka
Copy link
Contributor

relates #58719

this.format = Parameter.stringParam(
"format",
indexCreatedVersion.isLegacyIndexVersion(),
(n, c, o) -> LegacyFormatNames.compatibleFormat(XContentMapValues.nodeStringValue(o)),
Copy link
Contributor

Choose a reason for hiding this comment

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

just wanted to clarify. So LegacyFormatNames.compatibleFormat is returning a snake case for given camel case?
Would it be worth renaming to make this more clear?

@@ -197,6 +197,7 @@ public Set<Entry<String, NamedAnalyzer>> entrySet() {
mapperService.merge(indexMetadata, MapperService.MergeReason.MAPPING_RECOVERY);
}
} catch (Exception ex) {
logger.error("Failed to parse mappings for index [" + indexMetadata.getIndex() + "]", ex);
Copy link
Contributor

Choose a reason for hiding this comment

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

might be a dirty hack, but people on #84199 were tweaking the exception below to be null just to make upgrade/downgrade possible.
Maybe we could check what the exception is and if it was due to camelcase format we could return null as well?
I did not tested this though.

but at the same time, maybe your fix is preventing this exception from happening?

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 can remove the logger error, it was very hard to see why things fail without it, the original exception is hidden. My fix now prevents the exception to be thrown, but if we encountered one again I think we'll be in the same boat, not seeing what the actual error is.

@grcevski
Copy link
Contributor Author

I pushed a change to see if BWC tests pass with my code to fix up the mappings. I still need to write tests.

@elasticsearchmachine elasticsearchmachine changed the base branch from master to main July 22, 2022 23:05
@mark-vieira mark-vieira added v8.5.0 and removed v8.4.0 labels Jul 27, 2022
@grcevski
Copy link
Contributor Author

Tests for the upgrader are all done now.

Copy link
Member

@rjernst rjernst left a comment

Choose a reason for hiding this comment

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

A couple thoughts. Also, someone from the search area should review this.

@@ -90,7 +90,7 @@ public IndexMetadata verifyIndexMetadata(IndexMetadata indexMetadata, Version mi
// Next we have to run this otherwise if we try to create IndexSettings
// with broken settings it would fail in checkMappingsCompatibility
newMetadata = archiveBrokenIndexSettings(newMetadata);
checkMappingsCompatibility(newMetadata);
newMetadata = checkMappingsCompatibility(newMetadata);
Copy link
Member

Choose a reason for hiding this comment

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

Can we add a new method for doing the transformation? The "check" action to me implies nothing will change, it's just checking things.

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 only used here, so I'll simply rename the method and update the comments.

defaultFormat.pattern()
);

if (indexCreatedVersion.major <= Version.CURRENT.previousMajor().major) {
Copy link
Member

Choose a reason for hiding this comment

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

Should this version be a fixed constant? ie why not hardcoded to 8, or use one of the V_8_* constants (maybe 8.0.0?). Otherwise when the major version bumps this would start applying to 8.x.

/**
* Upgrades the format field of mapping properties
* <p>
* This method checks is the new mapping source has a different format than the original mapping, and if it
Copy link
Member

Choose a reason for hiding this comment

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

is -> if?

}

try {
return new CompressedXContent(sourceMap);
Copy link
Member

Choose a reason for hiding this comment

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

Could you keep track of whether any change was made above, so that the original parsedSource can be returned here and reference equality could be used by the caller to detect changes? That would make it less expensive when there aren't any changes (which is most of the time).

Map<String, Object> parsedProperties = getMappingProperties(newMap, mappingMetadata.type());
if (properties != null && parsedProperties != null) {
for (var property : properties.entrySet()) {
if (property.getValue()instanceof Map map) {
Copy link
Member

Choose a reason for hiding this comment

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

Will this handle object fields? It seems like it would only handle date fields at the root of mappings.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yeah I forgot about nested field mappings. I need to fix that.

* @param parsedSource the mapping source as it was parsed
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public static CompressedXContent upgradeFormatsIfNeeded(MappingMetadata mappingMetadata, CompressedXContent parsedSource) {
Copy link
Member

Choose a reason for hiding this comment

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

This method name implies it is a general upgrade, but isn't this specific to date fields, since you are looking for the format key?

@rjernst rjernst added the :Search/Search Search-related issues that do not fall into other categories label Jul 27, 2022
@elasticsearchmachine
Copy link
Collaborator

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

@elasticsearchmachine elasticsearchmachine added the Team:Search Meta label for search team label Jul 27, 2022
(Map<String, Object>) parsedMappings.get("properties")
);

boolean anyRuntimeChanges = upgradeDateFormatProperties(
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 didn't do anything here for dynamic_templates, they don't seem to trigger a parse of a Date field in the same way it's happening for 'properties' and 'runtime'.

@grcevski
Copy link
Contributor Author

Closing in favour of #88914

@grcevski grcevski closed this Jul 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>bug :Core/Infra/Core Core issues without another label :Search/Search Search-related issues that do not fall into other categories Team:Core/Infra Meta label for core/infra team Team:Search Meta label for search team v8.5.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deprecated feature use in 7.x index fails upgrade to 8.x but cannot be downgraded.
6 participants