Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -105,6 +105,8 @@
import static org.elasticsearch.cluster.metadata.IndexMetadata.SETTING_NUMBER_OF_SHARDS;
import static org.elasticsearch.cluster.metadata.MetadataCreateDataStreamService.validateTimestampFieldMapping;
import static org.elasticsearch.cluster.metadata.MetadataIndexTemplateService.resolveSettings;
import static org.elasticsearch.index.IndexModule.INDEX_RECOVERY_TYPE_SETTING;
import static org.elasticsearch.index.IndexModule.INDEX_STORE_TYPE_SETTING;

/**
* Service responsible for submitting create index requests
Expand Down Expand Up @@ -1140,6 +1142,9 @@ private static List<String> validateIndexCustomPath(Settings settings, @Nullable
*/
static List<String> validateShrinkIndex(ClusterState state, String sourceIndex, String targetIndexName, Settings targetIndexSettings) {
IndexMetadata sourceMetadata = validateResize(state, sourceIndex, targetIndexName, targetIndexSettings);
if ("snapshot".equals(INDEX_STORE_TYPE_SETTING.get(sourceMetadata.getSettings()))) {
throw new IllegalArgumentException("can't shrink searchable snapshot index [" + sourceIndex + ']');
}
assert INDEX_NUMBER_OF_SHARDS_SETTING.exists(targetIndexSettings);
IndexMetadata.selectShrinkShards(0, sourceMetadata, INDEX_NUMBER_OF_SHARDS_SETTING.get(targetIndexSettings));

Expand Down Expand Up @@ -1171,6 +1176,9 @@ static List<String> validateShrinkIndex(ClusterState state, String sourceIndex,

static void validateSplitIndex(ClusterState state, String sourceIndex, String targetIndexName, Settings targetIndexSettings) {
IndexMetadata sourceMetadata = validateResize(state, sourceIndex, targetIndexName, targetIndexSettings);
if ("snapshot".equals(INDEX_STORE_TYPE_SETTING.get(sourceMetadata.getSettings()))) {
throw new IllegalArgumentException("can't split searchable snapshot index [" + sourceIndex + ']');
}
IndexMetadata.selectSplitShard(0, sourceMetadata, IndexMetadata.INDEX_NUMBER_OF_SHARDS_SETTING.get(targetIndexSettings));
if (sourceMetadata.getCreationVersion().before(Version.V_6_0_0_alpha1)) {
// ensure we have a single type since this would make the splitting code considerably more complex
Expand All @@ -1182,6 +1190,15 @@ static void validateSplitIndex(ClusterState state, String sourceIndex, String ta

static void validateCloneIndex(ClusterState state, String sourceIndex, String targetIndexName, Settings targetIndexSettings) {
IndexMetadata sourceMetadata = validateResize(state, sourceIndex, targetIndexName, targetIndexSettings);
if ("snapshot".equals(INDEX_STORE_TYPE_SETTING.get(sourceMetadata.getSettings()))) {
for (Setting<?> nonCloneableSetting : Arrays.asList(INDEX_STORE_TYPE_SETTING, INDEX_RECOVERY_TYPE_SETTING)) {
if (nonCloneableSetting.exists(targetIndexSettings) == false) {
throw new IllegalArgumentException("can't clone searchable snapshot index [" + sourceIndex + "]; setting ["
+ nonCloneableSetting.getKey()
+ "] should be overridden");
}
}
}
IndexMetadata.selectCloneShard(0, sourceMetadata, INDEX_NUMBER_OF_SHARDS_SETTING.get(targetIndexSettings));
}

Expand All @@ -1201,7 +1218,6 @@ static IndexMetadata validateResize(ClusterState state, String sourceIndex, Stri
throw new IllegalArgumentException(String.format(Locale.ROOT, "cannot resize the write index [%s] for data stream [%s]",
sourceIndex, source.getParentDataStream().getName()));
}

// ensure index is read-only
if (state.blocks().indexBlocked(ClusterBlockLevel.WRITE, sourceIndex) == false) {
throw new IllegalStateException("index " + sourceIndex + " must be read-only to resize index. use \"index.blocks.write=true\"");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

package org.elasticsearch.xpack.searchablesnapshots;

import org.elasticsearch.action.admin.indices.shrink.ResizeType;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexModule;
import org.elasticsearch.repositories.fs.FsRepository;
import org.elasticsearch.test.ESIntegTestCase;
import org.elasticsearch.xpack.cluster.routing.allocation.DataTierAllocationDecider;
import org.elasticsearch.xpack.core.DataTier;
import org.junit.After;
import org.junit.Before;

import static java.util.Collections.singletonList;
import static org.elasticsearch.cluster.metadata.IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING;
import static org.elasticsearch.cluster.metadata.IndexMetadata.INDEX_NUMBER_OF_ROUTING_SHARDS_SETTING;
import static org.elasticsearch.cluster.metadata.IndexMetadata.INDEX_NUMBER_OF_SHARDS_SETTING;
import static org.elasticsearch.index.IndexSettings.INDEX_SOFT_DELETES_SETTING;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.xpack.core.searchablesnapshots.MountSearchableSnapshotRequest.Storage;
import static org.hamcrest.Matchers.equalTo;

@ESIntegTestCase.ClusterScope(numDataNodes = 1)
public class SearchableSnapshotsResizeIntegTests extends BaseFrozenSearchableSnapshotsIntegTestCase {

@Before
@Override
public void setUp() throws Exception {
super.setUp();
createRepository("repository", FsRepository.TYPE);
assertAcked(
prepareCreate(
"index",
Settings.builder()
.put(INDEX_NUMBER_OF_REPLICAS_SETTING.getKey(), 0)
.put(INDEX_NUMBER_OF_SHARDS_SETTING.getKey(), 2)
.put(INDEX_NUMBER_OF_ROUTING_SHARDS_SETTING.getKey(), 4)
.put(INDEX_SOFT_DELETES_SETTING.getKey(), true)
)
);
indexRandomDocs("index", scaledRandomIntBetween(0, 1_000));
createSnapshot("repository", "snapshot", singletonList("index"));
assertAcked(client().admin().indices().prepareDelete("index"));
mountSnapshot("repository", "snapshot", "index", "mounted-index", Settings.EMPTY, randomFrom(Storage.values()));
ensureGreen("mounted-index");
}

@After
@Override
public void tearDown() throws Exception {
assertAcked(client().admin().indices().prepareDelete("mounted-*"));
assertAcked(client().admin().cluster().prepareDeleteSnapshot("repository", "snapshot").get());
assertAcked(client().admin().cluster().prepareDeleteRepository("repository"));
super.tearDown();
}

public void testShrinkSearchableSnapshotIndex() {
final IllegalArgumentException exception = expectThrows(
IllegalArgumentException.class,
() -> client().admin()
.indices()
.prepareResizeIndex("mounted-index", "shrunk-index")
.setResizeType(ResizeType.SHRINK)
.setSettings(indexSettingsNoReplicas(1).build())
.get()
);
assertThat(exception.getMessage(), equalTo("can't shrink searchable snapshot index [mounted-index]"));
}

public void testSplitSearchableSnapshotIndex() {
final IllegalArgumentException exception = expectThrows(
IllegalArgumentException.class,
() -> client().admin()
.indices()
.prepareResizeIndex("mounted-index", "split-index")
.setResizeType(ResizeType.SPLIT)
.setSettings(indexSettingsNoReplicas(4).build())
.get()
);
assertThat(exception.getMessage(), equalTo("can't split searchable snapshot index [mounted-index]"));
}

public void testCloneSearchableSnapshotIndex() {
IllegalArgumentException exception = expectThrows(
IllegalArgumentException.class,
() -> client().admin().indices().prepareResizeIndex("mounted-index", "cloned-index").setResizeType(ResizeType.CLONE).get()
);
assertThat(
exception.getMessage(),
equalTo("can't clone searchable snapshot index [mounted-index]; setting [index.store.type] should be overridden")
);

exception = expectThrows(
IllegalArgumentException.class,
() -> client().admin()
.indices()
.prepareResizeIndex("mounted-index", "cloned-index")
.setResizeType(ResizeType.CLONE)
.setSettings(Settings.builder().putNull(IndexModule.INDEX_STORE_TYPE_SETTING.getKey()).build())
.get()
);
assertThat(
exception.getMessage(),
equalTo("can't clone searchable snapshot index [mounted-index]; setting [index.recovery.type] should be overridden")
);

assertAcked(
client().admin()
.indices()
.prepareResizeIndex("mounted-index", "cloned-index")
.setResizeType(ResizeType.CLONE)
.setSettings(
Settings.builder()
.putNull(IndexModule.INDEX_STORE_TYPE_SETTING.getKey())
.putNull(IndexModule.INDEX_RECOVERY_TYPE_SETTING.getKey())
.put(DataTierAllocationDecider.INDEX_ROUTING_PREFER, DataTier.DATA_HOT)
.put(INDEX_NUMBER_OF_REPLICAS_SETTING.getKey(), 0)
.build()
)
);
ensureGreen("cloned-index");
assertAcked(client().admin().indices().prepareDelete("cloned-index"));
}
}