Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
420b650
TODOS
williamrandolph Jul 19, 2023
cc42427
Merge branch 'main' into sysindex/new-mapping-version-format
williamrandolph Jul 20, 2023
441a2e9
Add modules version so tests will pass
williamrandolph Jul 24, 2023
633e58d
Add constant for old-style mapping version
williamrandolph Jul 25, 2023
9f6473d
Merge branch 'main' into sysindex/new-mapping-version-format
williamrandolph Jul 25, 2023
5fc2d00
Introduce constants
williamrandolph Jul 25, 2023
0fbb8fe
Fix up some tests
williamrandolph Jul 25, 2023
629b3f0
'mapping' -> 'mappings' for consistency
williamrandolph Jul 25, 2023
227936f
Set Fleet mappings versions
williamrandolph Jul 25, 2023
c2de130
Merge branch 'main' into sysindex/new-mapping-version-format
williamrandolph Jul 25, 2023
9074fd5
Update test
williamrandolph Jul 25, 2023
6c094c7
Bump starting versions and use placeholder for old versions
williamrandolph Jul 25, 2023
d522b26
Add versions for a few more test descriptors
williamrandolph Jul 26, 2023
85cde73
Merge branch 'main' into sysindex/new-mapping-version-format
williamrandolph Jul 26, 2023
3adac84
Try fixing ML mapping tests
williamrandolph Jul 26, 2023
2d0f806
spotless
williamrandolph Jul 26, 2023
04ac9e9
Fix watcher tests
williamrandolph Jul 27, 2023
59352c5
Back out 'legacy mapping' constant
williamrandolph Jul 27, 2023
e47b89c
Fix mappings resources
williamrandolph Jul 27, 2023
d56c1b7
Add version int to qa test
williamrandolph Jul 27, 2023
76ab8ac
Add version int to system index rest test
williamrandolph Jul 27, 2023
0185112
Insert new version into templates
williamrandolph Jul 27, 2023
55554fe
Merge branch 'main' into sysindex/new-mapping-version-format
williamrandolph Jul 27, 2023
c1670e2
Get the ML results index
williamrandolph Jul 27, 2023
7c77600
Drop version numbers to 1
williamrandolph Jul 27, 2023
43e4283
spotless
williamrandolph Jul 27, 2023
3fe560d
snake case is more idiomatic for json
williamrandolph Jul 27, 2023
0ae5160
Don't require correct order in CreateSystemIndicesIT
williamrandolph Jul 27, 2023
ea8d8bd
spotless
williamrandolph Jul 27, 2023
bede58b
Don't require correct order in mapping update IT either
williamrandolph Jul 27, 2023
a57809b
Add unit tests
williamrandolph Jul 28, 2023
1d2be99
spotless
williamrandolph Jul 28, 2023
8108e79
Clean up naming of deprecated Version
williamrandolph Jul 28, 2023
5b14a06
Merge branch 'main' into sysindex/new-mapping-version-format
williamrandolph Jul 28, 2023
3d56cf4
Merge branch 'main' into sysindex/new-mapping-version-format
williamrandolph Aug 3, 2023
d1bc552
Rename version meta key ('system' -> 'managed')
williamrandolph Aug 3, 2023
03c2a7c
Update mappings for ML indices if required
edsavage Aug 3, 2023
b87b446
Merge remote-tracking branch 'williamrandolph/sysindex/new-mapping-ve…
edsavage Aug 3, 2023
9f2eae4
Formatting
edsavage Aug 4, 2023
fced727
Trigger ML index mappings updates based on new index mappings version.
edsavage Aug 4, 2023
b71f681
Merge main
williamrandolph Aug 14, 2023
8b4e371
Remove TODOs tracked elsewhere
williamrandolph Aug 15, 2023
86d2f23
Remove TODOs tracked elsewhere pt 2
williamrandolph Aug 15, 2023
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 @@ -73,6 +73,7 @@

public class IngestGeoIpPlugin extends Plugin implements IngestPlugin, SystemIndexPlugin, Closeable, PersistentTaskPlugin, ActionPlugin {
public static final Setting<Long> CACHE_SIZE = Setting.longSetting("ingest.geoip.cache_size", 1000, 0, Setting.Property.NodeScope);
private static final int GEOIP_INDEX_MAPPINGS_VERSION = 1;

static Set<String> DEFAULT_DATABASE_FILENAMES = Set.of("GeoLite2-ASN.mmdb", "GeoLite2-City.mmdb", "GeoLite2-Country.mmdb");

Expand Down Expand Up @@ -225,6 +226,7 @@ private static XContentBuilder mappings() {
.startObject(SINGLE_MAPPING_NAME)
.startObject("_meta")
.field("version", Version.CURRENT)
.field(SystemIndexDescriptor.VERSION_META_KEY, GEOIP_INDEX_MAPPINGS_VERSION)
.endObject()
.field("dynamic", "strict")
.startObject("properties")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ static String createMapping(boolean descriptorManaged, boolean descriptorInterna
{
builder.startObject("_meta");
builder.field(VERSION_META_KEY, META_VERSION);
builder.field(SystemIndexDescriptor.VERSION_META_KEY, 1);
builder.field(DESCRIPTOR_MANAGED_META_KEY, descriptorManaged);
builder.field(DESCRIPTOR_INTERNAL_META_KEY, descriptorInternal);
builder.endObject();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ public Collection<SystemIndexDescriptor> getSystemIndexDescriptors(Settings sett
{
builder.startObject("_meta");
builder.field("version", Version.CURRENT.toString());
builder.field(SystemIndexDescriptor.VERSION_META_KEY, 1);
builder.endObject();

builder.field("dynamic", "strict");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ private static XContentBuilder mappings() {
.startObject(SINGLE_MAPPING_NAME)
.startObject("_meta")
.field("version", Version.CURRENT)
.field(SystemIndexDescriptor.VERSION_META_KEY, 1)
.endObject()
.field("dynamic", "strict")
.startObject("properties")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.elasticsearch.cluster.metadata.Template;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.CollectionUtils;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.indices.TestSystemIndexDescriptor;
import org.elasticsearch.indices.TestSystemIndexDescriptorAllowsTemplates;
import org.elasticsearch.indices.TestSystemIndexPlugin;
Expand All @@ -38,8 +39,6 @@
import org.junit.After;
import org.junit.Before;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
Expand All @@ -51,7 +50,6 @@

import static org.elasticsearch.indices.TestSystemIndexDescriptor.INDEX_NAME;
import static org.elasticsearch.indices.TestSystemIndexDescriptor.PRIMARY_INDEX_NAME;
import static org.elasticsearch.test.XContentTestUtils.convertToXContent;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
Expand Down Expand Up @@ -352,7 +350,6 @@ private void assertHasAliases(Set<String> aliasNames, String name, String primar

/**
* Fetch the mappings and settings for {@link TestSystemIndexDescriptor#INDEX_NAME} and verify that they match the expected values.
* Note that in the case of the mappings, this is just a dumb string comparison, so order of keys matters.
*/
private void assertMappingsAndSettings(String expectedMappings, String concreteIndex) {
final GetMappingsResponse getMappingsResponse = indicesAdmin().getMappings(new GetMappingsRequest().indices(INDEX_NAME))
Expand All @@ -366,11 +363,7 @@ private void assertMappingsAndSettings(String expectedMappings, String concreteI
);
final Map<String, Object> sourceAsMap = mappings.get(concreteIndex).getSourceAsMap();

try {
assertThat(convertToXContent(sourceAsMap, XContentType.JSON).utf8ToString(), equalTo(expectedMappings));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
assertThat(sourceAsMap, equalTo(XContentHelper.convertToMap(XContentType.JSON.xContent(), expectedMappings, false)));

final GetSettingsResponse getSettingsResponse = indicesAdmin().getSettings(new GetSettingsRequest().indices(INDEX_NAME))
.actionGet();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public Collection<SystemIndexDescriptor> getSystemIndexDescriptors(Settings sett
{
builder.startObject("_meta");
builder.field("version", Version.CURRENT.toString());
builder.field(SystemIndexDescriptor.VERSION_META_KEY, 1);
builder.endObject();

builder.field("dynamic", "strict");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,19 @@
import org.elasticsearch.cluster.metadata.MappingMetadata;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.CollectionUtils;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.xcontent.XContentType;
import org.junit.Before;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import static org.elasticsearch.indices.TestSystemIndexDescriptor.INDEX_NAME;
import static org.elasticsearch.indices.TestSystemIndexDescriptor.PRIMARY_INDEX_NAME;
import static org.elasticsearch.test.XContentTestUtils.convertToXContent;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.equalTo;

Expand Down Expand Up @@ -122,7 +120,6 @@ private void triggerClusterStateUpdates() {

/**
* Fetch the mappings and settings for {@link TestSystemIndexDescriptor#INDEX_NAME} and verify that they match the expected values.
* Note that in the case of the mappings, this is just a dumb string comparison, so order of keys matters.
*/
private void assertMappingsAndSettings(String expectedMappings) {
final GetMappingsResponse getMappingsResponse = indicesAdmin().getMappings(new GetMappingsRequest().indices(INDEX_NAME))
Expand All @@ -136,11 +133,7 @@ private void assertMappingsAndSettings(String expectedMappings) {
);
final Map<String, Object> sourceAsMap = mappings.get(PRIMARY_INDEX_NAME).getSourceAsMap();

try {
assertThat(convertToXContent(sourceAsMap, XContentType.JSON).utf8ToString(), equalTo(expectedMappings));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
assertThat(sourceAsMap, equalTo(XContentHelper.convertToMap(XContentType.JSON.xContent(), expectedMappings, false)));

final GetSettingsResponse getSettingsResponse = indicesAdmin().getSettings(new GetSettingsRequest().indices(INDEX_NAME))
.actionGet();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ public static String getOldMappings() {
builder.startObject();
{
builder.startObject("_meta");
builder.field(SystemIndexDescriptor.VERSION_META_KEY, 0);
builder.field("version", Version.CURRENT.previousMajor().toString());
builder.endObject();

Expand All @@ -123,6 +124,7 @@ public static String getNewMappings() {
builder.startObject();
{
builder.startObject("_meta");
builder.field(SystemIndexDescriptor.VERSION_META_KEY, 1);
builder.field("version", Version.CURRENT.toString());
builder.endObject();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import org.apache.lucene.util.automaton.CharacterRunAutomaton;
import org.apache.lucene.util.automaton.Operations;
import org.elasticsearch.Version;
import org.elasticsearch.action.admin.indices.create.AutoCreateAction;
import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction;
import org.elasticsearch.cluster.metadata.IndexMetadata;
import org.elasticsearch.cluster.metadata.Metadata;
import org.elasticsearch.cluster.metadata.SystemIndexMetadataUpgradeService;
Expand Down Expand Up @@ -130,18 +132,25 @@ public class SystemIndexDescriptor implements IndexPatternMatcher, Comparable<Sy

/**
* For internally-managed indices, specifies a key name under <code>_meta</code> in the index mappings
* that contains the index's mappings' version.
* that contains the index's mappings' {@link Version}. We need to read and write this field for
* backwards compatibility.
*/
private final String versionMetaKey;
private final String mappingsNodeVersionMetaKey;

/** The version meta key for the integer system index mapping version */
public static final String VERSION_META_KEY = "managed_index_mappings_version";

/** For internally-managed indices, specifies the origin to use when creating or updating the index */
private final String origin;

/** The minimum cluster node version required for this descriptor */
private final Version minimumNodeVersion;

/** Legacy mapping version from the descriptor */
private final Version mappingsNodeVersion;

/** Mapping version from the descriptor */
private final Version mappingVersion;
private final MappingsVersion mappingsVersion;

/** Whether there are dynamic fields in this descriptor's mappings */
private final boolean hasDynamicMappings;
Expand Down Expand Up @@ -189,7 +198,7 @@ public class SystemIndexDescriptor implements IndexPatternMatcher, Comparable<Sy
* @param settings The settings to apply to this index when auto-creating, if appropriate
* @param aliasName An alias for the index, or null
* @param indexFormat A value for the `index.format` setting. Pass 0 or higher.
* @param versionMetaKey a mapping key under <code>_meta</code> where a version can be found, which indicates the
* @param mappingsNodeVersionMetaKey a mapping key under <code>_meta</code> where a version can be found, which indicates the
* Elasticsearch version when the index was created.
* @param origin the client origin to use when creating this index. Internal system indices must not provide an origin, while external
* system indices must do so.
Expand All @@ -209,7 +218,7 @@ protected SystemIndexDescriptor(
Settings settings,
String aliasName,
int indexFormat,
String versionMetaKey,
String mappingsNodeVersionMetaKey,
String origin,
Version minimumNodeVersion,
Type type,
Expand Down Expand Up @@ -262,18 +271,22 @@ protected SystemIndexDescriptor(
Objects.requireNonNull(settings, "Must supply settings for a managed system index");
Strings.requireNonEmpty(mappings, "Must supply mappings for a managed system index");
Strings.requireNonEmpty(primaryIndex, "Must supply primaryIndex for a managed system index");
Strings.requireNonEmpty(versionMetaKey, "Must supply versionMetaKey for a managed system index");
Strings.requireNonEmpty(mappingsNodeVersionMetaKey, "Must supply nodeVersionMetaKey for a managed system index");
Strings.requireNonEmpty(origin, "Must supply origin for a managed system index");
if (settings.getAsInt(IndexMetadata.INDEX_FORMAT_SETTING.getKey(), 0) != indexFormat) {
throw new IllegalArgumentException("Descriptor index format does not match index format in managed settings");
}
this.mappingVersion = extractVersionFromMappings(mappings, versionMetaKey);
this.mappingsNodeVersion = extractNodeVersionFromMappings(mappings, mappingsNodeVersionMetaKey);
this.mappingsVersion = extractVersionFromMappings(mappings);
assert mappingsVersion.version >= 0 : "The mappings version must not be negative";

} else {
assert Objects.isNull(settings) : "Unmanaged index descriptors should not have settings";
assert Objects.isNull(mappings) : "Unmanaged index descriptors should not have mappings";
assert Objects.isNull(primaryIndex) : "Unmanaged index descriptors should not have a primary index";
assert Objects.isNull(versionMetaKey) : "Unmanaged index descriptors should not have a version meta key";
this.mappingVersion = null;
assert Objects.isNull(mappingsNodeVersionMetaKey) : "Unmanaged index descriptors should not have a version meta key";
this.mappingsNodeVersion = null;
this.mappingsVersion = null;
}

Objects.requireNonNull(allowedElasticProductOrigins, "allowedProductOrigins must not be null");
Expand Down Expand Up @@ -355,7 +368,7 @@ protected SystemIndexDescriptor(
throw new IllegalArgumentException("System indices must have " + IndexMetadata.SETTING_INDEX_HIDDEN + " set to true.");
}
this.indexFormat = indexFormat;
this.versionMetaKey = versionMetaKey;
this.mappingsNodeVersionMetaKey = mappingsNodeVersionMetaKey;
this.origin = origin;
this.minimumNodeVersion = minimumNodeVersion;
this.type = type;
Expand Down Expand Up @@ -450,9 +463,9 @@ public int getIndexFormat() {
return this.indexFormat;
}

public String getVersionMetaKey() {
public String getMappingsNodeVersionMetaKey() {
assert isAutomaticallyManaged() : "Do not request version meta keys for unmanaged system indices";
return this.versionMetaKey;
return this.mappingsNodeVersionMetaKey;
}

public Version getMinimumNodeVersion() {
Expand Down Expand Up @@ -506,11 +519,23 @@ public boolean allowsTemplates() {
return allowsTemplates;
}

public Version getMappingVersion() {
/**
* Use of the mappings {@link Version} should be replaced with the value returned from {@link #getMappingsVersion()}
* @return Elasticsearch version associated with this descriptor's mappings.
*/
@Deprecated
public Version getMappingsNodeVersion() {
if (isAutomaticallyManaged() == false) {
throw new IllegalStateException(this + " is not managed so there are no mappings or version");
}
return mappingsNodeVersion;
}

public MappingsVersion getMappingsVersion() {
if (isAutomaticallyManaged() == false) {
throw new IllegalStateException(this + " is not managed so there are no mappings or version");
}
return mappingVersion;
return mappingsVersion;
}

/**
Expand Down Expand Up @@ -612,6 +637,20 @@ public boolean isInternal() {
}
}

/**
* The version of the mapping, which should be stored as an int in a mapping metadata
* field. This will be used with prior index descriptors to determine which mappings
* should be used when creating a system index, and it will be used to determine when
* mappings should be updated with the latest mappings from the system index descriptor.
* See {@link SystemIndexMappingUpdateService}, {@link TransportCreateIndexAction},
* and {@link AutoCreateAction}.
* <p>
* Version should be a non-negative integer for a managed index, or -1 for unmanaged indices.
* The hash is a hash of the system index descriptor's mappings so that we can warn
* in case of inconsistencies across nodes.
*/
public record MappingsVersion(int version, int hash) {};

/**
* Provides a fluent API for building a {@link SystemIndexDescriptor}. Validation still happens in that class.
*/
Expand Down Expand Up @@ -818,8 +857,31 @@ static boolean findDynamicMapping(Map<String, Object> map) {
return false;
}

@SuppressWarnings("unchecked") // we do a lot of casting of maps
private static MappingsVersion extractVersionFromMappings(String mappings) {
final Map<String, Object> mappingsMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), mappings, true);
final Map<String, Object> doc = (Map<String, Object>) mappingsMap.get("_doc");
final Map<String, Object> meta;
final Map<String, Object> properties;
if (doc == null) {
meta = (Map<String, Object>) mappingsMap.get("_meta");
properties = (Map<String, Object>) mappingsMap.get("properties");
} else {
meta = (Map<String, Object>) doc.get("_meta");
properties = (Map<String, Object>) doc.get("properties");
}
if (meta == null) {
throw new IllegalStateException("mappings do not have _meta field");
}
final Integer value = (Integer) meta.get(VERSION_META_KEY);
if (value == null) {
throw new IllegalArgumentException("mappings do not have a version in _meta." + VERSION_META_KEY);
}
return new MappingsVersion(value, Objects.hash(properties));
}

@SuppressWarnings("unchecked")
private static Version extractVersionFromMappings(String mappings, String versionMetaKey) {
private static Version extractNodeVersionFromMappings(String mappings, String versionMetaKey) {
final Map<String, Object> mappingsMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), mappings, false);
final Map<String, Object> doc = (Map<String, Object>) mappingsMap.get("_doc");
final Map<String, Object> meta;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,15 +289,18 @@ private static Version readMappingVersion(SystemIndexDescriptor descriptor, Mapp
return Version.V_EMPTY;
}

final Object rawVersion = meta.get(descriptor.getVersionMetaKey());
final Object rawVersion = meta.get(descriptor.getMappingsNodeVersionMetaKey());
if (rawVersion instanceof Integer) {
// This can happen with old system indices, such as .tasks, which were created before we used an Elasticsearch
// version here. We should just replace the template to be sure.
return Version.V_EMPTY;
}
final String versionString = rawVersion != null ? rawVersion.toString() : null;
if (versionString == null) {
logger.warn("No value found in mappings for [_meta.{}], assuming mappings update required", descriptor.getVersionMetaKey());
logger.warn(
"No value found in mappings for [_meta.{}], assuming mappings update required",
descriptor.getMappingsNodeVersionMetaKey()
);
// If we called `Version.fromString(null)`, it would return `Version.CURRENT` and we wouldn't update the mappings
return Version.V_EMPTY;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public class SynonymsManagementAPIService {
public static final int MAX_SYNONYMS_SETS = 10_000;
private static final String SYNONYM_RULE_ID_FIELD = SynonymRule.ID_FIELD.getPreferredName();
private static final String SYNONYM_SETS_AGG_NAME = "synonym_sets_aggr";
private static final int SYNONYMS_INDEX_MAPPINGS_VERSION = 1;

private final Client client;

Expand Down Expand Up @@ -123,6 +124,7 @@ private static XContentBuilder mappings() {
builder.startObject("_meta");
{
builder.field("version", Version.CURRENT.toString());
builder.field(SystemIndexDescriptor.VERSION_META_KEY, SYNONYMS_INDEX_MAPPINGS_VERSION);
}
builder.endObject();
builder.field("dynamic", "strict");
Expand Down
Loading