mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-06-28 01:22:26 -04:00
parent
312f8315d3
commit
fe7818af04
23 changed files with 163 additions and 135 deletions
|
@ -137,7 +137,7 @@ public abstract class RestCompatTestTransformTask extends DefaultTask {
|
|||
// However, the folder can be arbitrarily nest so, a == a1/a2/a3, and the test name can include forward slashes, so c == c1/c2/c3
|
||||
// So we also need to support a1/a2/a3/b/c1/c2/c3
|
||||
|
||||
String[] testParts = fullTestName.split("/");
|
||||
String[] testParts = fullTestName.split("/", 3);
|
||||
if (testParts.length < 3) {
|
||||
throw new IllegalArgumentException(
|
||||
"To skip tests, all 3 parts [folder/file/test name] must be defined. found [" + fullTestName + "]"
|
||||
|
|
10
docs/changelog/116689.yaml
Normal file
10
docs/changelog/116689.yaml
Normal file
|
@ -0,0 +1,10 @@
|
|||
pr: 116689
|
||||
summary: Deprecate `_source.mode` in mappings
|
||||
area: Mapping
|
||||
type: deprecation
|
||||
issues: []
|
||||
deprecation:
|
||||
title: Deprecate `_source.mode` in mappings
|
||||
area: Mapping
|
||||
details: Configuring `_source.mode` in mappings is deprecated and will be removed in future versions. Use `index.mapping.source.mode` index setting instead.
|
||||
impact: Use `index.mapping.source.mode` index setting instead
|
|
@ -17,7 +17,6 @@ import org.elasticsearch.client.RestClient;
|
|||
import org.elasticsearch.common.network.InetAddresses;
|
||||
import org.elasticsearch.common.time.DateFormatter;
|
||||
import org.elasticsearch.common.time.FormatNames;
|
||||
import org.elasticsearch.test.MapMatcher;
|
||||
import org.elasticsearch.test.cluster.ElasticsearchCluster;
|
||||
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
|
||||
import org.hamcrest.Matcher;
|
||||
|
@ -30,9 +29,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.elasticsearch.test.MapMatcher.assertMap;
|
||||
import static org.elasticsearch.test.MapMatcher.matchesMap;
|
||||
|
||||
public class LogsIndexModeFullClusterRestartIT extends ParameterizedFullClusterRestartTestCase {
|
||||
|
||||
@ClassRule
|
||||
|
@ -169,22 +165,16 @@ public class LogsIndexModeFullClusterRestartIT extends ParameterizedFullClusterR
|
|||
assertOK(bulkIndexResponse);
|
||||
assertThat(entityAsMap(bulkIndexResponse).get("errors"), Matchers.is(false));
|
||||
|
||||
assertIndexMappingsAndSettings(0, Matchers.nullValue(), matchesMap().extraOk());
|
||||
assertIndexMappingsAndSettings(
|
||||
1,
|
||||
Matchers.equalTo("logsdb"),
|
||||
matchesMap().extraOk().entry("_source", Map.of("mode", "synthetic"))
|
||||
);
|
||||
assertIndexSettings(0, Matchers.nullValue());
|
||||
assertIndexSettings(1, Matchers.equalTo("logsdb"));
|
||||
}
|
||||
}
|
||||
|
||||
private void assertIndexMappingsAndSettings(int backingIndex, final Matcher<Object> indexModeMatcher, final MapMatcher mappingsMatcher)
|
||||
throws IOException {
|
||||
private void assertIndexSettings(int backingIndex, final Matcher<Object> indexModeMatcher) throws IOException {
|
||||
assertThat(
|
||||
getSettings(client(), getWriteBackingIndex(client(), "logs-apache-production", backingIndex)).get("index.mode"),
|
||||
indexModeMatcher
|
||||
);
|
||||
assertMap(getIndexMappingAsMap(getWriteBackingIndex(client(), "logs-apache-production", backingIndex)), mappingsMatcher);
|
||||
}
|
||||
|
||||
private static Request createDataStream(final String dataStreamName) {
|
||||
|
|
|
@ -17,7 +17,6 @@ import org.elasticsearch.client.RestClient;
|
|||
import org.elasticsearch.common.network.InetAddresses;
|
||||
import org.elasticsearch.common.time.DateFormatter;
|
||||
import org.elasticsearch.common.time.FormatNames;
|
||||
import org.elasticsearch.test.MapMatcher;
|
||||
import org.elasticsearch.test.cluster.ElasticsearchCluster;
|
||||
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
|
||||
import org.hamcrest.Matcher;
|
||||
|
@ -30,9 +29,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.elasticsearch.test.MapMatcher.assertMap;
|
||||
import static org.elasticsearch.test.MapMatcher.matchesMap;
|
||||
|
||||
public class LogsIndexModeRollingUpgradeIT extends AbstractRollingUpgradeTestCase {
|
||||
|
||||
@ClassRule()
|
||||
|
@ -160,14 +156,10 @@ public class LogsIndexModeRollingUpgradeIT extends AbstractRollingUpgradeTestCas
|
|||
assertOK(bulkIndexResponse);
|
||||
assertThat(entityAsMap(bulkIndexResponse).get("errors"), Matchers.is(false));
|
||||
|
||||
assertIndexMappingsAndSettings(0, Matchers.nullValue(), matchesMap().extraOk());
|
||||
assertIndexMappingsAndSettings(1, Matchers.nullValue(), matchesMap().extraOk());
|
||||
assertIndexMappingsAndSettings(2, Matchers.nullValue(), matchesMap().extraOk());
|
||||
assertIndexMappingsAndSettings(
|
||||
3,
|
||||
Matchers.equalTo("logsdb"),
|
||||
matchesMap().extraOk().entry("_source", Map.of("mode", "synthetic"))
|
||||
);
|
||||
assertIndexSettings(0, Matchers.nullValue());
|
||||
assertIndexSettings(1, Matchers.nullValue());
|
||||
assertIndexSettings(2, Matchers.nullValue());
|
||||
assertIndexSettings(3, Matchers.equalTo("logsdb"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,13 +175,11 @@ public class LogsIndexModeRollingUpgradeIT extends AbstractRollingUpgradeTestCas
|
|||
assertOK(client().performRequest(request));
|
||||
}
|
||||
|
||||
private void assertIndexMappingsAndSettings(int backingIndex, final Matcher<Object> indexModeMatcher, final MapMatcher mappingsMatcher)
|
||||
throws IOException {
|
||||
private void assertIndexSettings(int backingIndex, final Matcher<Object> indexModeMatcher) throws IOException {
|
||||
assertThat(
|
||||
getSettings(client(), getWriteBackingIndex(client(), "logs-apache-production", backingIndex)).get("index.mode"),
|
||||
indexModeMatcher
|
||||
);
|
||||
assertMap(getIndexMappingAsMap(getWriteBackingIndex(client(), "logs-apache-production", backingIndex)), mappingsMatcher);
|
||||
}
|
||||
|
||||
private static Request createDataStream(final String dataStreamName) {
|
||||
|
|
|
@ -60,4 +60,10 @@ tasks.named("yamlRestCompatTestTransform").configure ({ task ->
|
|||
task.skipTest("cat.aliases/10_basic/Deprecated local parameter", "CAT APIs not covered by compatibility policy")
|
||||
task.skipTest("cat.shards/10_basic/Help", "sync_id is removed in 9.0")
|
||||
task.skipTest("search/500_date_range/from, to, include_lower, include_upper deprecated", "deprecated parameters are removed in 9.0")
|
||||
task.skipTest("tsdb/20_mapping/stored source is supported", "no longer serialize source_mode")
|
||||
task.skipTest("tsdb/20_mapping/Synthetic source", "no longer serialize source_mode")
|
||||
task.skipTest("logsdb/10_settings/create logs index", "no longer serialize source_mode")
|
||||
task.skipTest("logsdb/20_source_mapping/stored _source mode is supported", "no longer serialize source_mode")
|
||||
task.skipTest("logsdb/20_source_mapping/include/exclude is supported with stored _source", "no longer serialize source_mode")
|
||||
task.skipTest("logsdb/20_source_mapping/synthetic _source is default", "no longer serialize source_mode")
|
||||
})
|
||||
|
|
|
@ -76,11 +76,6 @@ create logs index:
|
|||
- is_true: test
|
||||
- match: { test.settings.index.mode: "logsdb" }
|
||||
|
||||
- do:
|
||||
indices.get_mapping:
|
||||
index: test
|
||||
- match: { test.mappings._source.mode: synthetic }
|
||||
|
||||
---
|
||||
using default timestamp field mapping:
|
||||
- requires:
|
||||
|
|
|
@ -13,10 +13,10 @@ synthetic _source is default:
|
|||
index:
|
||||
mode: logsdb
|
||||
- do:
|
||||
indices.get:
|
||||
indices.get_settings:
|
||||
index: test-default-source
|
||||
|
||||
- match: { test-default-source.mappings._source.mode: "synthetic" }
|
||||
- match: { test-default-source.settings.index.mode: logsdb }
|
||||
- match: { test-default-source.settings.index.mapping.source.mode: null }
|
||||
|
||||
---
|
||||
stored _source mode is supported:
|
||||
|
@ -28,11 +28,12 @@ stored _source mode is supported:
|
|||
index:
|
||||
mode: logsdb
|
||||
mapping.source.mode: stored
|
||||
- do:
|
||||
indices.get:
|
||||
index: test-stored-source
|
||||
|
||||
- match: { test-stored-source.mappings._source.mode: "stored" }
|
||||
- do:
|
||||
indices.get_settings:
|
||||
index: test-stored-source
|
||||
- match: { test-stored-source.settings.index.mode: logsdb }
|
||||
- match: { test-stored-source.settings.index.mapping.source.mode: stored }
|
||||
|
||||
---
|
||||
disabled _source is not supported:
|
||||
|
@ -110,7 +111,6 @@ include/exclude is supported with stored _source:
|
|||
indices.get:
|
||||
index: test-includes
|
||||
|
||||
- match: { test-includes.mappings._source.mode: "stored" }
|
||||
- match: { test-includes.mappings._source.includes: ["a"] }
|
||||
|
||||
- do:
|
||||
|
@ -129,5 +129,4 @@ include/exclude is supported with stored _source:
|
|||
indices.get:
|
||||
index: test-excludes
|
||||
|
||||
- match: { test-excludes.mappings._source.mode: "stored" }
|
||||
- match: { test-excludes.mappings._source.excludes: ["b"] }
|
||||
|
|
|
@ -450,11 +450,6 @@ nested fields:
|
|||
type: long
|
||||
time_series_metric: gauge
|
||||
|
||||
- do:
|
||||
indices.get_mapping: {}
|
||||
|
||||
- match: {tsdb-synthetic.mappings._source.mode: synthetic}
|
||||
|
||||
---
|
||||
stored source is supported:
|
||||
- requires:
|
||||
|
@ -486,12 +481,6 @@ stored source is supported:
|
|||
type: keyword
|
||||
time_series_dimension: true
|
||||
|
||||
- do:
|
||||
indices.get:
|
||||
index: tsdb_index
|
||||
|
||||
- match: { tsdb_index.mappings._source.mode: "stored" }
|
||||
|
||||
---
|
||||
disabled source is not supported:
|
||||
- requires:
|
||||
|
|
|
@ -11,6 +11,7 @@ package org.elasticsearch.index;
|
|||
|
||||
import org.elasticsearch.cluster.metadata.IndexMetadata;
|
||||
import org.elasticsearch.cluster.metadata.Metadata;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.compress.CompressedXContent;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.core.CheckedFunction;
|
||||
|
@ -54,7 +55,7 @@ public interface IndexSettingProvider {
|
|||
/**
|
||||
* Infrastructure class that holds services that can be used by {@link IndexSettingProvider} instances.
|
||||
*/
|
||||
record Parameters(CheckedFunction<IndexMetadata, MapperService, IOException> mapperServiceFactory) {
|
||||
record Parameters(ClusterService clusterService, CheckedFunction<IndexMetadata, MapperService, IOException> mapperServiceFactory) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -134,6 +134,7 @@ public class IndexVersions {
|
|||
public static final IndexVersion UPGRADE_TO_LUCENE_10_0_0 = def(9_000_00_0, Version.LUCENE_10_0_0);
|
||||
public static final IndexVersion LOGSDB_DEFAULT_IGNORE_DYNAMIC_BEYOND_LIMIT = def(9_001_00_0, Version.LUCENE_10_0_0);
|
||||
public static final IndexVersion TIME_BASED_K_ORDERED_DOC_ID = def(9_002_00_0, Version.LUCENE_10_0_0);
|
||||
public static final IndexVersion DEPRECATE_SOURCE_MODE_MAPPER = def(9_003_00_0, Version.LUCENE_10_0_0);
|
||||
/*
|
||||
* STOP! READ THIS FIRST! No, really,
|
||||
* ____ _____ ___ ____ _ ____ _____ _ ____ _____ _ _ ___ ____ _____ ___ ____ ____ _____ _
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.apache.lucene.util.BytesRef;
|
|||
import org.elasticsearch.common.Explicit;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.logging.DeprecationCategory;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.CollectionUtils;
|
||||
|
@ -38,6 +39,7 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
public class SourceFieldMapper extends MetadataFieldMapper {
|
||||
public static final NodeFeature SYNTHETIC_SOURCE_FALLBACK = new NodeFeature("mapper.source.synthetic_source_fallback");
|
||||
|
@ -68,6 +70,9 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
|||
return indexMode.defaultSourceMode().name();
|
||||
}, "index.mapping.source.mode", value -> {}, Setting.Property.Final, Setting.Property.IndexScope);
|
||||
|
||||
public static final String DEPRECATION_WARNING = "Configuring source mode in mappings is deprecated and will be removed "
|
||||
+ "in future versions. Use [index.mapping.source.mode] index setting instead.";
|
||||
|
||||
/** The source mode */
|
||||
public enum Mode {
|
||||
DISABLED,
|
||||
|
@ -79,28 +84,32 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
|||
null,
|
||||
Explicit.IMPLICIT_TRUE,
|
||||
Strings.EMPTY_ARRAY,
|
||||
Strings.EMPTY_ARRAY
|
||||
Strings.EMPTY_ARRAY,
|
||||
false
|
||||
);
|
||||
|
||||
private static final SourceFieldMapper STORED = new SourceFieldMapper(
|
||||
Mode.STORED,
|
||||
Explicit.IMPLICIT_TRUE,
|
||||
Strings.EMPTY_ARRAY,
|
||||
Strings.EMPTY_ARRAY
|
||||
Strings.EMPTY_ARRAY,
|
||||
false
|
||||
);
|
||||
|
||||
private static final SourceFieldMapper SYNTHETIC = new SourceFieldMapper(
|
||||
Mode.SYNTHETIC,
|
||||
Explicit.IMPLICIT_TRUE,
|
||||
Strings.EMPTY_ARRAY,
|
||||
Strings.EMPTY_ARRAY
|
||||
Strings.EMPTY_ARRAY,
|
||||
false
|
||||
);
|
||||
|
||||
private static final SourceFieldMapper DISABLED = new SourceFieldMapper(
|
||||
Mode.DISABLED,
|
||||
Explicit.IMPLICIT_TRUE,
|
||||
Strings.EMPTY_ARRAY,
|
||||
Strings.EMPTY_ARRAY
|
||||
Strings.EMPTY_ARRAY,
|
||||
false
|
||||
);
|
||||
|
||||
public static class Defaults {
|
||||
|
@ -134,16 +143,7 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
|||
* The default mode for TimeSeries is left empty on purpose, so that mapping printings include the synthetic
|
||||
* source mode.
|
||||
*/
|
||||
private final Parameter<Mode> mode = new Parameter<>(
|
||||
"mode",
|
||||
true,
|
||||
() -> null,
|
||||
(n, c, o) -> Mode.valueOf(o.toString().toUpperCase(Locale.ROOT)),
|
||||
m -> toType(m).enabled.explicit() ? null : toType(m).mode,
|
||||
(b, n, v) -> b.field(n, v.toString().toLowerCase(Locale.ROOT)),
|
||||
v -> v.toString().toLowerCase(Locale.ROOT)
|
||||
).setMergeValidator((previous, current, conflicts) -> (previous == current) || current != Mode.STORED)
|
||||
.setSerializerCheck((includeDefaults, isConfigured, value) -> value != null); // don't emit if `enabled` is configured
|
||||
private final Parameter<Mode> mode;
|
||||
private final Parameter<List<String>> includes = Parameter.stringArrayParam(
|
||||
"includes",
|
||||
false,
|
||||
|
@ -158,15 +158,28 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
|||
private final Settings settings;
|
||||
|
||||
private final IndexMode indexMode;
|
||||
private boolean serializeMode;
|
||||
|
||||
private final boolean supportsNonDefaultParameterValues;
|
||||
|
||||
public Builder(IndexMode indexMode, final Settings settings, boolean supportsCheckForNonDefaultParams) {
|
||||
public Builder(IndexMode indexMode, final Settings settings, boolean supportsCheckForNonDefaultParams, boolean serializeMode) {
|
||||
super(Defaults.NAME);
|
||||
this.settings = settings;
|
||||
this.indexMode = indexMode;
|
||||
this.supportsNonDefaultParameterValues = supportsCheckForNonDefaultParams == false
|
||||
|| settings.getAsBoolean(LOSSY_PARAMETERS_ALLOWED_SETTING_NAME, true);
|
||||
this.serializeMode = serializeMode;
|
||||
this.mode = new Parameter<>(
|
||||
"mode",
|
||||
true,
|
||||
() -> null,
|
||||
(n, c, o) -> Mode.valueOf(o.toString().toUpperCase(Locale.ROOT)),
|
||||
m -> toType(m).enabled.explicit() ? null : toType(m).mode,
|
||||
(b, n, v) -> b.field(n, v.toString().toLowerCase(Locale.ROOT)),
|
||||
v -> v.toString().toLowerCase(Locale.ROOT)
|
||||
).setMergeValidator((previous, current, conflicts) -> (previous == current) || current != Mode.STORED)
|
||||
// don't emit if `enabled` is configured
|
||||
.setSerializerCheck((includeDefaults, isConfigured, value) -> serializeMode && value != null);
|
||||
}
|
||||
|
||||
public Builder setSynthetic() {
|
||||
|
@ -219,21 +232,22 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
|||
if (sourceMode == Mode.SYNTHETIC && (includes.getValue().isEmpty() == false || excludes.getValue().isEmpty() == false)) {
|
||||
throw new IllegalArgumentException("filtering the stored _source is incompatible with synthetic source");
|
||||
}
|
||||
|
||||
SourceFieldMapper sourceFieldMapper;
|
||||
if (isDefault()) {
|
||||
if (mode.isConfigured()) {
|
||||
serializeMode = true;
|
||||
}
|
||||
final SourceFieldMapper sourceFieldMapper;
|
||||
if (isDefault() && sourceMode == null) {
|
||||
// Needed for bwc so that "mode" is not serialized in case of a standard index with stored source.
|
||||
if (sourceMode == null) {
|
||||
sourceFieldMapper = DEFAULT;
|
||||
} else {
|
||||
sourceFieldMapper = resolveStaticInstance(sourceMode);
|
||||
}
|
||||
sourceFieldMapper = DEFAULT;
|
||||
} else if (isDefault() && serializeMode == false && sourceMode != null) {
|
||||
sourceFieldMapper = resolveStaticInstance(sourceMode);
|
||||
} else {
|
||||
sourceFieldMapper = new SourceFieldMapper(
|
||||
sourceMode,
|
||||
enabled.get(),
|
||||
includes.getValue().toArray(Strings.EMPTY_ARRAY),
|
||||
excludes.getValue().toArray(Strings.EMPTY_ARRAY)
|
||||
excludes.getValue().toArray(Strings.EMPTY_ARRAY),
|
||||
serializeMode
|
||||
);
|
||||
}
|
||||
if (indexMode != null) {
|
||||
|
@ -283,15 +297,29 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
|||
if (indexMode == IndexMode.STANDARD && settingSourceMode == Mode.STORED) {
|
||||
return DEFAULT;
|
||||
}
|
||||
|
||||
return resolveStaticInstance(settingSourceMode);
|
||||
if (c.indexVersionCreated().onOrAfter(IndexVersions.DEPRECATE_SOURCE_MODE_MAPPER)) {
|
||||
return resolveStaticInstance(settingSourceMode);
|
||||
} else {
|
||||
return new SourceFieldMapper(settingSourceMode, Explicit.IMPLICIT_TRUE, Strings.EMPTY_ARRAY, Strings.EMPTY_ARRAY, true);
|
||||
}
|
||||
},
|
||||
c -> new Builder(
|
||||
c.getIndexSettings().getMode(),
|
||||
c.getSettings(),
|
||||
c.indexVersionCreated().onOrAfter(IndexVersions.SOURCE_MAPPER_LOSSY_PARAMS_CHECK)
|
||||
c.indexVersionCreated().onOrAfter(IndexVersions.SOURCE_MAPPER_LOSSY_PARAMS_CHECK),
|
||||
c.indexVersionCreated().before(IndexVersions.DEPRECATE_SOURCE_MODE_MAPPER)
|
||||
)
|
||||
);
|
||||
) {
|
||||
@Override
|
||||
public MetadataFieldMapper.Builder parse(String name, Map<String, Object> node, MappingParserContext parserContext)
|
||||
throws MapperParsingException {
|
||||
assert name.equals(SourceFieldMapper.NAME) : name;
|
||||
if (parserContext.indexVersionCreated().after(IndexVersions.DEPRECATE_SOURCE_MODE_MAPPER) && node.containsKey("mode")) {
|
||||
deprecationLogger.critical(DeprecationCategory.MAPPINGS, "mapping_source_mode", SourceFieldMapper.DEPRECATION_WARNING);
|
||||
}
|
||||
return super.parse(name, node, parserContext);
|
||||
}
|
||||
};
|
||||
|
||||
static final class SourceFieldType extends MappedFieldType {
|
||||
private final boolean enabled;
|
||||
|
@ -330,8 +358,9 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
|||
}
|
||||
}
|
||||
|
||||
// nullable for bwc reasons
|
||||
// nullable for bwc reasons - TODO: fold this into serializeMode
|
||||
private final @Nullable Mode mode;
|
||||
private final boolean serializeMode;
|
||||
private final Explicit<Boolean> enabled;
|
||||
|
||||
/** indicates whether the source will always exist and be complete, for use by features like the update API */
|
||||
|
@ -341,7 +370,7 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
|||
private final String[] excludes;
|
||||
private final SourceFilter sourceFilter;
|
||||
|
||||
private SourceFieldMapper(Mode mode, Explicit<Boolean> enabled, String[] includes, String[] excludes) {
|
||||
private SourceFieldMapper(Mode mode, Explicit<Boolean> enabled, String[] includes, String[] excludes, boolean serializeMode) {
|
||||
super(new SourceFieldType((enabled.explicit() && enabled.value()) || (enabled.explicit() == false && mode != Mode.DISABLED)));
|
||||
this.mode = mode;
|
||||
this.enabled = enabled;
|
||||
|
@ -349,6 +378,7 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
|||
this.includes = includes;
|
||||
this.excludes = excludes;
|
||||
this.complete = stored() && sourceFilter == null;
|
||||
this.serializeMode = serializeMode;
|
||||
}
|
||||
|
||||
private static SourceFilter buildSourceFilter(String[] includes, String[] excludes) {
|
||||
|
@ -419,7 +449,7 @@ public class SourceFieldMapper extends MetadataFieldMapper {
|
|||
|
||||
@Override
|
||||
public FieldMapper.Builder getMergeBuilder() {
|
||||
return new Builder(null, Settings.EMPTY, false).init(this);
|
||||
return new Builder(null, Settings.EMPTY, false, serializeMode).init(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -820,7 +820,7 @@ class NodeConstruction {
|
|||
.searchOperationListeners(searchOperationListeners)
|
||||
.build();
|
||||
|
||||
final var parameters = new IndexSettingProvider.Parameters(indicesService::createIndexMapperServiceForValidation);
|
||||
final var parameters = new IndexSettingProvider.Parameters(clusterService, indicesService::createIndexMapperServiceForValidation);
|
||||
IndexSettingProviders indexSettingProviders = new IndexSettingProviders(
|
||||
Sets.union(
|
||||
builtinIndexSettingProviders(),
|
||||
|
|
|
@ -69,7 +69,7 @@ public class DynamicFieldsBuilderTests extends ESTestCase {
|
|||
XContentParser parser = createParser(JsonXContent.jsonXContent, source);
|
||||
SourceToParse sourceToParse = new SourceToParse("test", new BytesArray(source), XContentType.JSON);
|
||||
|
||||
SourceFieldMapper sourceMapper = new SourceFieldMapper.Builder(null, Settings.EMPTY, false).setSynthetic().build();
|
||||
SourceFieldMapper sourceMapper = new SourceFieldMapper.Builder(null, Settings.EMPTY, false, false).setSynthetic().build();
|
||||
RootObjectMapper root = new RootObjectMapper.Builder("_doc", Optional.empty()).add(
|
||||
new PassThroughObjectMapper.Builder("labels").setPriority(0).setContainsDimensions().dynamic(ObjectMapper.Dynamic.TRUE)
|
||||
).build(MapperBuilderContext.root(false, false));
|
||||
|
|
|
@ -247,14 +247,14 @@ public class SourceFieldMapperTests extends MetadataMapperTestCase {
|
|||
});
|
||||
DocumentMapper mapper = createTimeSeriesModeDocumentMapper(mapping);
|
||||
assertTrue(mapper.sourceMapper().isSynthetic());
|
||||
assertEquals("{\"_source\":{\"mode\":\"synthetic\"}}", mapper.sourceMapper().toString());
|
||||
assertEquals("{\"_source\":{}}", mapper.sourceMapper().toString());
|
||||
}
|
||||
|
||||
public void testSyntheticSourceWithLogsIndexMode() throws IOException {
|
||||
XContentBuilder mapping = fieldMapping(b -> { b.field("type", "keyword"); });
|
||||
DocumentMapper mapper = createLogsModeDocumentMapper(mapping);
|
||||
assertTrue(mapper.sourceMapper().isSynthetic());
|
||||
assertEquals("{\"_source\":{\"mode\":\"synthetic\"}}", mapper.sourceMapper().toString());
|
||||
assertEquals("{\"_source\":{}}", mapper.sourceMapper().toString());
|
||||
}
|
||||
|
||||
public void testSupportsNonDefaultParameterValues() throws IOException {
|
||||
|
|
|
@ -384,7 +384,7 @@ public class SearchExecutionContextTests extends ESTestCase {
|
|||
|
||||
public void testSyntheticSourceSearchLookup() throws IOException {
|
||||
// Build a mapping using synthetic source
|
||||
SourceFieldMapper sourceMapper = new SourceFieldMapper.Builder(null, Settings.EMPTY, false).setSynthetic().build();
|
||||
SourceFieldMapper sourceMapper = new SourceFieldMapper.Builder(null, Settings.EMPTY, false, false).setSynthetic().build();
|
||||
RootObjectMapper root = new RootObjectMapper.Builder("_doc", Optional.empty()).add(
|
||||
new KeywordFieldMapper.Builder("cat", IndexVersion.current()).ignoreAbove(100)
|
||||
).build(MapperBuilderContext.root(true, false));
|
||||
|
|
|
@ -69,6 +69,7 @@ import org.elasticsearch.health.node.selection.HealthNode;
|
|||
import org.elasticsearch.index.IndexSettings;
|
||||
import org.elasticsearch.index.IndexVersion;
|
||||
import org.elasticsearch.index.IndexVersions;
|
||||
import org.elasticsearch.index.mapper.SourceFieldMapper;
|
||||
import org.elasticsearch.index.query.QueryBuilder;
|
||||
import org.elasticsearch.index.seqno.ReplicationTracker;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
@ -112,6 +113,7 @@ import java.util.EnumSet;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
@ -1827,8 +1829,9 @@ public abstract class ESRestTestCase extends ESTestCase {
|
|||
|
||||
if (settings != null && settings.getAsBoolean(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), true) == false) {
|
||||
expectSoftDeletesWarning(request, name);
|
||||
} else if (isSyntheticSourceConfiguredInMapping(mapping)) {
|
||||
request.setOptions(expectVersionSpecificWarnings(v -> v.compatible(SourceFieldMapper.DEPRECATION_WARNING)));
|
||||
}
|
||||
|
||||
final Response response = client.performRequest(request);
|
||||
try (var parser = responseAsParser(response)) {
|
||||
return TestResponseParsers.parseCreateIndexResponse(parser);
|
||||
|
@ -1872,6 +1875,27 @@ public abstract class ESRestTestCase extends ESTestCase {
|
|||
}));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected static boolean isSyntheticSourceConfiguredInMapping(String mapping) {
|
||||
if (mapping == null) {
|
||||
return false;
|
||||
}
|
||||
var mappings = XContentHelper.convertToMap(
|
||||
JsonXContent.jsonXContent,
|
||||
mapping.trim().startsWith("{") ? mapping : '{' + mapping + '}',
|
||||
false
|
||||
);
|
||||
if (mappings.containsKey("_doc")) {
|
||||
mappings = (Map<String, Object>) mappings.get("_doc");
|
||||
}
|
||||
Map<String, Object> sourceMapper = (Map<String, Object>) mappings.get(SourceFieldMapper.NAME);
|
||||
if (sourceMapper == null) {
|
||||
return false;
|
||||
}
|
||||
Object mode = sourceMapper.get("mode");
|
||||
return mode != null && mode.toString().toLowerCase(Locale.ROOT).equals("synthetic");
|
||||
}
|
||||
|
||||
protected static Map<String, Object> getIndexSettings(String index) throws IOException {
|
||||
Request request = new Request("GET", "/" + index + "/_settings");
|
||||
request.addParameter("flat_settings", "true");
|
||||
|
@ -2269,7 +2293,7 @@ public abstract class ESRestTestCase extends ESTestCase {
|
|||
*/
|
||||
protected static IndexVersion minimumIndexVersion() throws IOException {
|
||||
final Request request = new Request("GET", "_nodes");
|
||||
request.addParameter("filter_path", "nodes.*.version,nodes.*.max_index_version");
|
||||
request.addParameter("filter_path", "nodes.*.version,nodes.*.max_index_version,nodes.*.index_version");
|
||||
|
||||
final Response response = adminClient().performRequest(request);
|
||||
final Map<String, Object> nodes = ObjectPath.createFromResponse(response).evaluate("nodes");
|
||||
|
@ -2277,10 +2301,13 @@ public abstract class ESRestTestCase extends ESTestCase {
|
|||
IndexVersion minVersion = null;
|
||||
for (Map.Entry<String, Object> node : nodes.entrySet()) {
|
||||
Map<?, ?> nodeData = (Map<?, ?>) node.getValue();
|
||||
String versionStr = (String) nodeData.get("max_index_version");
|
||||
Object versionStr = nodeData.get("index_version");
|
||||
if (versionStr == null) {
|
||||
versionStr = nodeData.get("max_index_version");
|
||||
}
|
||||
// fallback on version if index version is not there
|
||||
IndexVersion indexVersion = versionStr != null
|
||||
? IndexVersion.fromId(Integer.parseInt(versionStr))
|
||||
? IndexVersion.fromId(Integer.parseInt(versionStr.toString()))
|
||||
: IndexVersion.fromId(
|
||||
parseLegacyVersion((String) nodeData.get("version")).map(Version::id).orElse(IndexVersions.MINIMUM_COMPATIBLE.id())
|
||||
);
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.elasticsearch.common.Strings;
|
|||
import org.elasticsearch.common.logging.HeaderWarning;
|
||||
import org.elasticsearch.core.Tuple;
|
||||
import org.elasticsearch.core.UpdateForV9;
|
||||
import org.elasticsearch.index.mapper.SourceFieldMapper;
|
||||
import org.elasticsearch.rest.action.admin.indices.RestPutIndexTemplateAction;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestExecutionContext;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestResponse;
|
||||
|
@ -495,6 +496,8 @@ public class DoSection implements ExecutableSection {
|
|||
}
|
||||
}
|
||||
|
||||
unexpected.removeIf(s -> s.endsWith(SourceFieldMapper.DEPRECATION_WARNING + "\""));
|
||||
|
||||
if (unexpected.isEmpty() == false
|
||||
|| unmatched.isEmpty() == false
|
||||
|| missing.isEmpty() == false
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.index.IndexSettings;
|
||||
import org.elasticsearch.index.mapper.DateFieldMapper;
|
||||
import org.elasticsearch.index.mapper.SourceFieldMapper;
|
||||
import org.elasticsearch.repositories.fs.FsRepository;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
|
@ -366,8 +367,10 @@ public class FollowIndexIT extends ESCCRRestTestCase {
|
|||
final String leaderIndexName = "synthetic_leader";
|
||||
if ("leader".equals(targetCluster)) {
|
||||
logger.info("Running against leader cluster");
|
||||
createIndex(adminClient(), leaderIndexName, Settings.EMPTY, """
|
||||
"_source": {"mode": "synthetic"},
|
||||
Settings settings = Settings.builder()
|
||||
.put(SourceFieldMapper.INDEX_MAPPER_SOURCE_MODE_SETTING.getKey(), SourceFieldMapper.Mode.SYNTHETIC)
|
||||
.build();
|
||||
createIndex(adminClient(), leaderIndexName, settings, """
|
||||
"properties": {"kwd": {"type": "keyword"}}}""", null);
|
||||
for (int i = 0; i < numDocs; i++) {
|
||||
logger.info("Indexing doc [{}]", i);
|
||||
|
@ -392,7 +395,6 @@ public class FollowIndexIT extends ESCCRRestTestCase {
|
|||
}
|
||||
assertBusy(() -> {
|
||||
verifyDocuments(client(), followIndexName, numDocs);
|
||||
assertMap(getIndexMappingAsMap(followIndexName), matchesMap().extraOk().entry("_source", Map.of("mode", "synthetic")));
|
||||
if (overrideNumberOfReplicas) {
|
||||
assertMap(getIndexSettingsAsMap(followIndexName), matchesMap().extraOk().entry("index.number_of_replicas", "0"));
|
||||
} else {
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.elasticsearch.client.Response;
|
|||
import org.elasticsearch.client.ResponseException;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.network.NetworkAddress;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.core.CheckedConsumer;
|
||||
import org.elasticsearch.geo.GeometryTestUtils;
|
||||
import org.elasticsearch.index.mapper.BlockLoader;
|
||||
|
@ -1456,16 +1457,12 @@ public abstract class FieldExtractorTestCase extends ESRestTestCase {
|
|||
}
|
||||
|
||||
private static void createIndex(String name, CheckedConsumer<XContentBuilder, IOException> mapping) throws IOException {
|
||||
Request request = new Request("PUT", "/" + name);
|
||||
XContentBuilder index = JsonXContent.contentBuilder().prettyPrint().startObject();
|
||||
index.startObject("mappings");
|
||||
mapping.accept(index);
|
||||
index.endObject();
|
||||
index.endObject();
|
||||
String configStr = Strings.toString(index);
|
||||
logger.info("index: {} {}", name, configStr);
|
||||
request.setJsonEntity(configStr);
|
||||
client().performRequest(request);
|
||||
ESRestTestCase.createIndex(name, Settings.EMPTY, configStr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -67,10 +67,13 @@ public class LogsDBPlugin extends Plugin implements ActionPlugin {
|
|||
if (DiscoveryNode.isStateless(settings)) {
|
||||
return List.of(logsdbIndexModeSettingsProvider);
|
||||
}
|
||||
return List.of(
|
||||
new SyntheticSourceIndexSettingsProvider(licenseService, parameters.mapperServiceFactory(), logsdbIndexModeSettingsProvider),
|
||||
logsdbIndexModeSettingsProvider
|
||||
var syntheticSettingProvider = new SyntheticSourceIndexSettingsProvider(
|
||||
licenseService,
|
||||
parameters.mapperServiceFactory(),
|
||||
logsdbIndexModeSettingsProvider,
|
||||
() -> parameters.clusterService().state().nodes().getMinSupportedIndexVersion()
|
||||
);
|
||||
return List.of(syntheticSettingProvider, logsdbIndexModeSettingsProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.elasticsearch.index.mapper.SourceFieldMapper;
|
|||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.elasticsearch.cluster.metadata.IndexMetadata.INDEX_ROUTING_PATH;
|
||||
|
||||
|
@ -39,15 +40,18 @@ final class SyntheticSourceIndexSettingsProvider implements IndexSettingProvider
|
|||
private final SyntheticSourceLicenseService syntheticSourceLicenseService;
|
||||
private final CheckedFunction<IndexMetadata, MapperService, IOException> mapperServiceFactory;
|
||||
private final LogsdbIndexModeSettingsProvider logsdbIndexModeSettingsProvider;
|
||||
private final Supplier<IndexVersion> createdIndexVersion;
|
||||
|
||||
SyntheticSourceIndexSettingsProvider(
|
||||
SyntheticSourceLicenseService syntheticSourceLicenseService,
|
||||
CheckedFunction<IndexMetadata, MapperService, IOException> mapperServiceFactory,
|
||||
LogsdbIndexModeSettingsProvider logsdbIndexModeSettingsProvider
|
||||
LogsdbIndexModeSettingsProvider logsdbIndexModeSettingsProvider,
|
||||
Supplier<IndexVersion> createdIndexVersion
|
||||
) {
|
||||
this.syntheticSourceLicenseService = syntheticSourceLicenseService;
|
||||
this.mapperServiceFactory = mapperServiceFactory;
|
||||
this.logsdbIndexModeSettingsProvider = logsdbIndexModeSettingsProvider;
|
||||
this.createdIndexVersion = createdIndexVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -148,7 +152,7 @@ final class SyntheticSourceIndexSettingsProvider implements IndexSettingProvider
|
|||
);
|
||||
int shardReplicas = indexTemplateAndCreateRequestSettings.getAsInt(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, 0);
|
||||
var finalResolvedSettings = Settings.builder()
|
||||
.put(IndexMetadata.SETTING_VERSION_CREATED, IndexVersion.current())
|
||||
.put(IndexMetadata.SETTING_VERSION_CREATED, createdIndexVersion.get())
|
||||
.put(indexTemplateAndCreateRequestSettings)
|
||||
.put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, dummyShards)
|
||||
.put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, shardReplicas)
|
||||
|
|
|
@ -15,6 +15,7 @@ import org.elasticsearch.common.settings.Settings;
|
|||
import org.elasticsearch.core.Tuple;
|
||||
import org.elasticsearch.index.IndexMode;
|
||||
import org.elasticsearch.index.IndexSettings;
|
||||
import org.elasticsearch.index.IndexVersion;
|
||||
import org.elasticsearch.index.MapperTestUtils;
|
||||
import org.elasticsearch.index.mapper.SourceFieldMapper;
|
||||
import org.elasticsearch.license.MockLicenseState;
|
||||
|
@ -54,7 +55,7 @@ public class SyntheticSourceIndexSettingsProviderTests extends ESTestCase {
|
|||
provider = new SyntheticSourceIndexSettingsProvider(syntheticSourceLicenseService, im -> {
|
||||
newMapperServiceCounter.incrementAndGet();
|
||||
return MapperTestUtils.newMapperService(xContentRegistry(), createTempDir(), im.getSettings(), im.getIndex().getName());
|
||||
}, getLogsdbIndexModeSettingsProvider(false));
|
||||
}, getLogsdbIndexModeSettingsProvider(false), IndexVersion::current);
|
||||
newMapperServiceCounter.set(0);
|
||||
}
|
||||
|
||||
|
@ -336,7 +337,8 @@ public class SyntheticSourceIndexSettingsProviderTests extends ESTestCase {
|
|||
provider = new SyntheticSourceIndexSettingsProvider(
|
||||
syntheticSourceLicenseService,
|
||||
im -> MapperTestUtils.newMapperService(xContentRegistry(), createTempDir(), im.getSettings(), im.getIndex().getName()),
|
||||
getLogsdbIndexModeSettingsProvider(true)
|
||||
getLogsdbIndexModeSettingsProvider(true),
|
||||
IndexVersion::current
|
||||
);
|
||||
final Settings settings = Settings.EMPTY;
|
||||
|
||||
|
|
|
@ -470,13 +470,7 @@ create an index with time_series index mode and synthetic source:
|
|||
indices.get_settings:
|
||||
index: "test_time_series_index_mode_synthetic"
|
||||
- match: { test_time_series_index_mode_synthetic.settings.index.mode: time_series }
|
||||
|
||||
|
||||
- do:
|
||||
indices.get_mapping:
|
||||
index: test_time_series_index_mode_synthetic
|
||||
|
||||
- match: { test_time_series_index_mode_synthetic.mappings._source.mode: synthetic }
|
||||
- match: { test_time_series_index_mode_synthetic.settings.index.mapping.source.mode: synthetic }
|
||||
|
||||
---
|
||||
create an index with logsdb index mode and synthetic source:
|
||||
|
@ -493,12 +487,7 @@ create an index with logsdb index mode and synthetic source:
|
|||
indices.get_settings:
|
||||
index: "test_logsdb_index_mode_synthetic"
|
||||
- match: { test_logsdb_index_mode_synthetic.settings.index.mode: logsdb }
|
||||
|
||||
- do:
|
||||
indices.get_mapping:
|
||||
index: test_logsdb_index_mode_synthetic
|
||||
|
||||
- match: { test_logsdb_index_mode_synthetic.mappings._source.mode: synthetic }
|
||||
- match: { test_logsdb_index_mode_synthetic.settings.index.mapping.source.mode: synthetic }
|
||||
|
||||
---
|
||||
create an index with time_series index mode and stored source:
|
||||
|
@ -524,12 +513,7 @@ create an index with time_series index mode and stored source:
|
|||
indices.get_settings:
|
||||
index: "test_time_series_index_mode_undefined"
|
||||
- match: { test_time_series_index_mode_undefined.settings.index.mode: time_series }
|
||||
|
||||
- do:
|
||||
indices.get_mapping:
|
||||
index: test_time_series_index_mode_undefined
|
||||
|
||||
- match: { test_time_series_index_mode_undefined.mappings._source.mode: stored }
|
||||
- match: { test_time_series_index_mode_undefined.settings.index.mapping.source.mode: stored }
|
||||
|
||||
---
|
||||
create an index with logsdb index mode and stored source:
|
||||
|
@ -546,12 +530,7 @@ create an index with logsdb index mode and stored source:
|
|||
indices.get_settings:
|
||||
index: "test_logsdb_index_mode_undefined"
|
||||
- match: { test_logsdb_index_mode_undefined.settings.index.mode: logsdb }
|
||||
|
||||
- do:
|
||||
indices.get_mapping:
|
||||
index: test_logsdb_index_mode_undefined
|
||||
|
||||
- match: { test_logsdb_index_mode_undefined.mappings._source.mode: stored }
|
||||
- match: { test_logsdb_index_mode_undefined.settings.index.mapping.source.mode: stored }
|
||||
|
||||
---
|
||||
create an index with time_series index mode and disabled source:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue