Skip to content

Commit

Permalink
[7.x] Enforce data_frozen for partial searchable snapshot _tier_prefe…
Browse files Browse the repository at this point in the history
…rence (elastic#71155) (elastic#71342)

* Enforce data_frozen for partial searchable snapshot _tier_preference (elastic#71155)

We already set `data_frozen` for partial searchable snapshots when they are mounted (elastic#70786), and
automatically convert values other than the frozen role automatically for these snapshots when the
metadata is loaded (elastic#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]>
  • Loading branch information
dakrone and elasticmachine authored Apr 13, 2021
1 parent c652efe commit a49341c
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import static org.elasticsearch.xpack.core.DataTier.DATA_FROZEN;
Expand Down Expand Up @@ -65,8 +66,21 @@ public class DataTierAllocationDecider extends AllocationDecider {
VALIDATOR, Setting.Property.Dynamic, Setting.Property.IndexScope);
public static final Setting<String> INDEX_ROUTING_EXCLUDE_SETTING = Setting.simpleString(INDEX_ROUTING_EXCLUDE,
VALIDATOR, Setting.Property.Dynamic, Setting.Property.IndexScope);
public static final Setting<String> INDEX_ROUTING_PREFER_SETTING = Setting.simpleString(INDEX_ROUTING_PREFER,
VALIDATOR, Setting.Property.Dynamic, Setting.Property.IndexScope);
public static final Setting<String> INDEX_ROUTING_PREFER_SETTING = new Setting<String>(new Setting.SimpleKey(INDEX_ROUTING_PREFER),
DataTierValidator::getDefaultTierPreference, Function.identity(), VALIDATOR,
Setting.Property.Dynamic, Setting.Property.IndexScope) {
@Override
public String get(Settings settings) {
if (SearchableSnapshotsConstants.isPartialSearchableSnapshotIndex(settings)) {
// Partial searchable snapshot indices should be restricted to
// only data_frozen when reading the setting, or else validation fails.
return DATA_FROZEN;
} else {
// Otherwise pass through to the regular setting retrieval
return super.get(settings);
}
}
};

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

public static String getDefaultTierPreference(Settings settings) {
if (SearchableSnapshotsConstants.isPartialSearchableSnapshotIndex(settings)) {
return DATA_FROZEN;
} else {
return "";
}
}

@Override
public void validate(String value) {
validateTierSetting(value);
}

@Override
public void validate(String value, Map<Setting<?>, Object> settings) {
if (Strings.hasText(value) && SearchableSnapshotsConstants.isPartialSearchableSnapshotIndex(settings) == false) {
String[] split = value.split(",");
if (Arrays.stream(split).anyMatch(DATA_FROZEN::equals)) {
throw new IllegalArgumentException("[" + DATA_FROZEN + "] tier can only be used for partial searchable snapshots");
public void validate(String value, Map<Setting<?>, Object> settings, boolean exists) {
if (exists && value != null) {
if (SearchableSnapshotsConstants.isPartialSearchableSnapshotIndex(settings)) {
if (value.equals(DATA_FROZEN) == false) {
throw new IllegalArgumentException("only the [" + DATA_FROZEN +
"] tier preference may be used for partial searchable snapshots (got: [" + value + "])");
}
} else {
String[] split = value.split(",");
if (Arrays.stream(split).anyMatch(DATA_FROZEN::equals)) {
throw new IllegalArgumentException("[" + DATA_FROZEN + "] tier can only be used for partial searchable snapshots");
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public static boolean isPartialSearchableSnapshotIndex(Map<Setting<?>, Object> i
&& (boolean) indexSettings.get(SNAPSHOT_PARTIAL_SETTING);
}

public static boolean isPartialSearchableSnapshotIndex(Settings indexSettings) {
return SNAPSHOT_DIRECTORY_FACTORY_KEY.equals(INDEX_STORE_TYPE_SETTING.get(indexSettings))
&& SNAPSHOT_PARTIAL_SETTING.get(indexSettings);
}

public static final String CACHE_FETCH_ASYNC_THREAD_POOL_NAME = "searchable_snapshots_cache_fetch_async";
public static final String CACHE_FETCH_ASYNC_THREAD_POOL_SETTING = "xpack.searchable_snapshots.cache_fetch_async_thread_pool";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -730,22 +730,26 @@ public void testFrozenIllegalForRegularIndices() {
}

public void testFrozenLegalForPartialSnapshot() {
List<String> tierList = new ArrayList<>(randomSubsetOf(DataTier.ALL_DATA_TIERS));
if (tierList.contains(DATA_FROZEN) == false) {
tierList.add(DATA_FROZEN);
}
Randomness.shuffle(tierList);

String value = Strings.join(tierList, ",");
Setting<String> setting = randomTierSetting();
Settings.Builder builder = Settings.builder().put(setting.getKey(), value);
Settings.Builder builder = Settings.builder().put(setting.getKey(), DATA_FROZEN);
builder.put(IndexModule.INDEX_STORE_TYPE_SETTING.getKey(), SearchableSnapshotsConstants.SNAPSHOT_DIRECTORY_FACTORY_KEY);
builder.put(SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING.getKey(), true);

Settings settings = builder.build();

// validate do not throw
assertThat(setting.get(settings), equalTo(value));
assertThat(setting.get(settings), equalTo(DATA_FROZEN));
}

public void testDefaultValueForPreference() {
assertThat(DataTierAllocationDecider.INDEX_ROUTING_PREFER_SETTING.get(Settings.EMPTY), equalTo(""));

Settings.Builder builder = Settings.builder();
builder.put(IndexModule.INDEX_STORE_TYPE_SETTING.getKey(), SearchableSnapshotsConstants.SNAPSHOT_DIRECTORY_FACTORY_KEY);
builder.put(SearchableSnapshotsConstants.SNAPSHOT_PARTIAL_SETTING.getKey(), true);

Settings settings = builder.build();
assertThat(DataTierAllocationDecider.INDEX_ROUTING_PREFER_SETTING.get(settings), equalTo(DATA_FROZEN));
}

public Setting<String> randomTierSetting() {
Expand Down

0 comments on commit a49341c

Please sign in to comment.