Skip to content

Commit 0e1d2d9

Browse files
authored
Prohibit changes to index mode, source, and sort settings during resize (#115812)
Relates to #115811, but applies to resize requests. The index.mode, source.mode, and index.sort.* settings cannot be modified during resize, as this may lead to data corruption or issues retrieving _source. This change enforces a restriction on modifying these settings during resize. While a fine-grained check could allow equivalent settings, it seems simpler and safer to reject resize requests if any of these settings are specified.
1 parent 4ecdfbb commit 0e1d2d9

File tree

4 files changed

+67
-8
lines changed

4 files changed

+67
-8
lines changed

docs/changelog/115812.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 115812
2+
summary: "Prohibit changes to index mode, source, and sort settings during resize"
3+
area: Logs
4+
type: bug
5+
issues: []

server/src/internalClusterTest/java/org/elasticsearch/action/admin/indices/create/CloneIndexIT.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
1313
import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
1414
import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider;
15+
import org.elasticsearch.common.ValidationException;
1516
import org.elasticsearch.common.settings.Settings;
1617
import org.elasticsearch.index.IndexVersion;
1718
import org.elasticsearch.index.query.TermsQueryBuilder;
@@ -20,9 +21,12 @@
2021
import org.elasticsearch.test.index.IndexVersionUtils;
2122
import org.elasticsearch.xcontent.XContentType;
2223

24+
import java.util.List;
25+
2326
import static org.elasticsearch.action.admin.indices.create.ShrinkIndexIT.assertNoResizeSourceIndexSettings;
2427
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
2528
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
29+
import static org.hamcrest.Matchers.containsString;
2630
import static org.hamcrest.Matchers.equalTo;
2731

2832
public class CloneIndexIT extends ESIntegTestCase {
@@ -109,4 +113,47 @@ public void testCreateCloneIndex() {
109113

110114
}
111115

116+
public void testResizeChangeIndexMode() {
117+
prepareCreate("source").setSettings(indexSettings(1, 0)).setMapping("@timestamp", "type=date", "host.name", "type=keyword").get();
118+
updateIndexSettings(Settings.builder().put("index.blocks.write", true), "source");
119+
List<Settings> indexSettings = List.of(
120+
Settings.builder().put("index.mode", "logsdb").build(),
121+
Settings.builder().put("index.mode", "time_series").put("index.routing_path", "host.name").build(),
122+
Settings.builder().put("index.mode", "lookup").build()
123+
);
124+
for (Settings settings : indexSettings) {
125+
IllegalArgumentException error = expectThrows(IllegalArgumentException.class, () -> {
126+
indicesAdmin().prepareResizeIndex("source", "target").setResizeType(ResizeType.CLONE).setSettings(settings).get();
127+
});
128+
assertThat(error.getMessage(), equalTo("can't change setting [index.mode] during resize"));
129+
}
130+
}
131+
132+
public void testResizeChangeSyntheticSource() {
133+
prepareCreate("source").setSettings(indexSettings(between(1, 5), 0))
134+
.setMapping("@timestamp", "type=date", "host.name", "type=keyword")
135+
.get();
136+
updateIndexSettings(Settings.builder().put("index.blocks.write", true), "source");
137+
IllegalArgumentException error = expectThrows(IllegalArgumentException.class, () -> {
138+
indicesAdmin().prepareResizeIndex("source", "target")
139+
.setResizeType(ResizeType.CLONE)
140+
.setSettings(Settings.builder().put("index.mapping.source.mode", "synthetic").putNull("index.blocks.write").build())
141+
.get();
142+
});
143+
assertThat(error.getMessage(), containsString("can't change setting [index.mapping.source.mode] during resize"));
144+
}
145+
146+
public void testResizeChangeIndexSorts() {
147+
prepareCreate("source").setSettings(indexSettings(between(1, 5), 0))
148+
.setMapping("@timestamp", "type=date", "host.name", "type=keyword")
149+
.get();
150+
updateIndexSettings(Settings.builder().put("index.blocks.write", true), "source");
151+
ValidationException error = expectThrows(ValidationException.class, () -> {
152+
indicesAdmin().prepareResizeIndex("source", "target")
153+
.setResizeType(ResizeType.CLONE)
154+
.setSettings(Settings.builder().putList("index.sort.field", List.of("@timestamp")).build())
155+
.get();
156+
});
157+
assertThat(error.getMessage(), containsString("can't override index sort when resizing an index"));
158+
}
112159
}

server/src/internalClusterTest/java/org/elasticsearch/index/LookupIndexModeIT.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ public void testResizeRegularIndexToLookup() {
198198
IllegalArgumentException.class,
199199
() -> client().admin().indices().execute(ResizeAction.INSTANCE, shrink).actionGet()
200200
);
201-
assertThat(error.getMessage(), equalTo("can't change index.mode of index [regular-1] from [standard] to [lookup]"));
201+
assertThat(error.getMessage(), equalTo("can't change setting [index.mode] during resize"));
202202
}
203203

204204
public void testDoNotOverrideAutoExpandReplicas() {

server/src/main/java/org/elasticsearch/cluster/metadata/MetadataCreateIndexService.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,13 @@
6262
import org.elasticsearch.index.IndexSettingProvider;
6363
import org.elasticsearch.index.IndexSettingProviders;
6464
import org.elasticsearch.index.IndexSettings;
65+
import org.elasticsearch.index.IndexSortConfig;
6566
import org.elasticsearch.index.IndexVersion;
6667
import org.elasticsearch.index.IndexVersions;
6768
import org.elasticsearch.index.mapper.DocumentMapper;
6869
import org.elasticsearch.index.mapper.MapperService;
6970
import org.elasticsearch.index.mapper.MapperService.MergeReason;
71+
import org.elasticsearch.index.mapper.SourceFieldMapper;
7072
import org.elasticsearch.index.query.SearchExecutionContext;
7173
import org.elasticsearch.index.shard.IndexLongFieldRange;
7274
import org.elasticsearch.indices.IndexCreationException;
@@ -1567,6 +1569,15 @@ static void validateCloneIndex(
15671569
IndexMetadata.selectCloneShard(0, sourceMetadata, INDEX_NUMBER_OF_SHARDS_SETTING.get(targetIndexSettings));
15681570
}
15691571

1572+
private static final Set<String> UNMODIFIABLE_SETTINGS_DURING_RESIZE = Set.of(
1573+
IndexSettings.MODE.getKey(),
1574+
SourceFieldMapper.INDEX_MAPPER_SOURCE_MODE_SETTING.getKey(),
1575+
IndexSortConfig.INDEX_SORT_FIELD_SETTING.getKey(),
1576+
IndexSortConfig.INDEX_SORT_ORDER_SETTING.getKey(),
1577+
IndexSortConfig.INDEX_SORT_MODE_SETTING.getKey(),
1578+
IndexSortConfig.INDEX_SORT_MISSING_SETTING.getKey()
1579+
);
1580+
15701581
static IndexMetadata validateResize(
15711582
Metadata metadata,
15721583
ClusterBlocks clusterBlocks,
@@ -1604,13 +1615,9 @@ static IndexMetadata validateResize(
16041615
// of if the source shards are divisible by the number of target shards
16051616
IndexMetadata.getRoutingFactor(sourceMetadata.getNumberOfShards(), INDEX_NUMBER_OF_SHARDS_SETTING.get(targetIndexSettings));
16061617
}
1607-
if (targetIndexSettings.hasValue(IndexSettings.MODE.getKey())) {
1608-
IndexMode oldMode = Objects.requireNonNullElse(sourceMetadata.getIndexMode(), IndexMode.STANDARD);
1609-
IndexMode newMode = IndexSettings.MODE.get(targetIndexSettings);
1610-
if (newMode != oldMode) {
1611-
throw new IllegalArgumentException(
1612-
"can't change index.mode of index [" + sourceIndex + "] from [" + oldMode + "] to [" + newMode + "]"
1613-
);
1618+
for (String setting : UNMODIFIABLE_SETTINGS_DURING_RESIZE) {
1619+
if (targetIndexSettings.hasValue(setting)) {
1620+
throw new IllegalArgumentException("can't change setting [" + setting + "] during resize");
16141621
}
16151622
}
16161623
return sourceMetadata;

0 commit comments

Comments
 (0)