Skip to content

Commit a49341c

Browse files
[7.x] Enforce data_frozen for partial searchable snapshot _tier_preference (#71155) (#71342)
* Enforce data_frozen for partial searchable snapshot _tier_preference (#71155) We already set `data_frozen` for partial searchable snapshots when they are mounted (#70786), and automatically convert values other than the frozen role automatically for these snapshots when the metadata is loaded (#71014). This commit makes the `_tier_preference` setting validate that the setting is *only* `data_frozen` when set on a partial searchable snapshot index. * Handle mixed version clusters with pre-7.13.0 frozen SBIs * Fix checkstyyyyyyyyle * Pass index version in settings for test * Unconditionally return only data_frozen for setting Co-authored-by: Elastic Machine <[email protected]>
1 parent c652efe commit a49341c

File tree

3 files changed

+54
-16
lines changed

3 files changed

+54
-16
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierAllocationDecider.java

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import java.util.Map;
3232
import java.util.Optional;
3333
import java.util.Set;
34+
import java.util.function.Function;
3435
import java.util.stream.Collectors;
3536

3637
import static org.elasticsearch.xpack.core.DataTier.DATA_FROZEN;
@@ -65,8 +66,21 @@ public class DataTierAllocationDecider extends AllocationDecider {
6566
VALIDATOR, Setting.Property.Dynamic, Setting.Property.IndexScope);
6667
public static final Setting<String> INDEX_ROUTING_EXCLUDE_SETTING = Setting.simpleString(INDEX_ROUTING_EXCLUDE,
6768
VALIDATOR, Setting.Property.Dynamic, Setting.Property.IndexScope);
68-
public static final Setting<String> INDEX_ROUTING_PREFER_SETTING = Setting.simpleString(INDEX_ROUTING_PREFER,
69-
VALIDATOR, Setting.Property.Dynamic, Setting.Property.IndexScope);
69+
public static final Setting<String> INDEX_ROUTING_PREFER_SETTING = new Setting<String>(new Setting.SimpleKey(INDEX_ROUTING_PREFER),
70+
DataTierValidator::getDefaultTierPreference, Function.identity(), VALIDATOR,
71+
Setting.Property.Dynamic, Setting.Property.IndexScope) {
72+
@Override
73+
public String get(Settings settings) {
74+
if (SearchableSnapshotsConstants.isPartialSearchableSnapshotIndex(settings)) {
75+
// Partial searchable snapshot indices should be restricted to
76+
// only data_frozen when reading the setting, or else validation fails.
77+
return DATA_FROZEN;
78+
} else {
79+
// Otherwise pass through to the regular setting retrieval
80+
return super.get(settings);
81+
}
82+
}
83+
};
7084

7185
private static void validateTierSetting(String setting) {
7286
if (Strings.hasText(setting)) {
@@ -84,17 +98,32 @@ private static class DataTierValidator implements Setting.Validator<String> {
8498
org.elasticsearch.common.collect.List.of(IndexModule.INDEX_STORE_TYPE_SETTING,
8599
SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING);
86100

101+
public static String getDefaultTierPreference(Settings settings) {
102+
if (SearchableSnapshotsConstants.isPartialSearchableSnapshotIndex(settings)) {
103+
return DATA_FROZEN;
104+
} else {
105+
return "";
106+
}
107+
}
108+
87109
@Override
88110
public void validate(String value) {
89111
validateTierSetting(value);
90112
}
91113

92114
@Override
93-
public void validate(String value, Map<Setting<?>, Object> settings) {
94-
if (Strings.hasText(value) && SearchableSnapshotsConstants.isPartialSearchableSnapshotIndex(settings) == false) {
95-
String[] split = value.split(",");
96-
if (Arrays.stream(split).anyMatch(DATA_FROZEN::equals)) {
97-
throw new IllegalArgumentException("[" + DATA_FROZEN + "] tier can only be used for partial searchable snapshots");
115+
public void validate(String value, Map<Setting<?>, Object> settings, boolean exists) {
116+
if (exists && value != null) {
117+
if (SearchableSnapshotsConstants.isPartialSearchableSnapshotIndex(settings)) {
118+
if (value.equals(DATA_FROZEN) == false) {
119+
throw new IllegalArgumentException("only the [" + DATA_FROZEN +
120+
"] tier preference may be used for partial searchable snapshots (got: [" + value + "])");
121+
}
122+
} else {
123+
String[] split = value.split(",");
124+
if (Arrays.stream(split).anyMatch(DATA_FROZEN::equals)) {
125+
throw new IllegalArgumentException("[" + DATA_FROZEN + "] tier can only be used for partial searchable snapshots");
126+
}
98127
}
99128
}
100129
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshotsConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ public static boolean isPartialSearchableSnapshotIndex(Map<Setting<?>, Object> i
4242
&& (boolean) indexSettings.get(SNAPSHOT_PARTIAL_SETTING);
4343
}
4444

45+
public static boolean isPartialSearchableSnapshotIndex(Settings indexSettings) {
46+
return SNAPSHOT_DIRECTORY_FACTORY_KEY.equals(INDEX_STORE_TYPE_SETTING.get(indexSettings))
47+
&& SNAPSHOT_PARTIAL_SETTING.get(indexSettings);
48+
}
49+
4550
public static final String CACHE_FETCH_ASYNC_THREAD_POOL_NAME = "searchable_snapshots_cache_fetch_async";
4651
public static final String CACHE_FETCH_ASYNC_THREAD_POOL_SETTING = "xpack.searchable_snapshots.cache_fetch_async_thread_pool";
4752

x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/cluster/routing/allocation/DataTierAllocationDeciderTests.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -730,22 +730,26 @@ public void testFrozenIllegalForRegularIndices() {
730730
}
731731

732732
public void testFrozenLegalForPartialSnapshot() {
733-
List<String> tierList = new ArrayList<>(randomSubsetOf(DataTier.ALL_DATA_TIERS));
734-
if (tierList.contains(DATA_FROZEN) == false) {
735-
tierList.add(DATA_FROZEN);
736-
}
737-
Randomness.shuffle(tierList);
738-
739-
String value = Strings.join(tierList, ",");
740733
Setting<String> setting = randomTierSetting();
741-
Settings.Builder builder = Settings.builder().put(setting.getKey(), value);
734+
Settings.Builder builder = Settings.builder().put(setting.getKey(), DATA_FROZEN);
742735
builder.put(IndexModule.INDEX_STORE_TYPE_SETTING.getKey(), SearchableSnapshotsConstants.SNAPSHOT_DIRECTORY_FACTORY_KEY);
743736
builder.put(SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING.getKey(), true);
744737

745738
Settings settings = builder.build();
746739

747740
// validate do not throw
748-
assertThat(setting.get(settings), equalTo(value));
741+
assertThat(setting.get(settings), equalTo(DATA_FROZEN));
742+
}
743+
744+
public void testDefaultValueForPreference() {
745+
assertThat(DataTierAllocationDecider.INDEX_ROUTING_PREFER_SETTING.get(Settings.EMPTY), equalTo(""));
746+
747+
Settings.Builder builder = Settings.builder();
748+
builder.put(IndexModule.INDEX_STORE_TYPE_SETTING.getKey(), SearchableSnapshotsConstants.SNAPSHOT_DIRECTORY_FACTORY_KEY);
749+
builder.put(SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING.getKey(), true);
750+
751+
Settings settings = builder.build();
752+
assertThat(DataTierAllocationDecider.INDEX_ROUTING_PREFER_SETTING.get(settings), equalTo(DATA_FROZEN));
749753
}
750754

751755
public Setting<String> randomTierSetting() {

0 commit comments

Comments
 (0)