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 @@ -72,6 +72,7 @@
import java.nio.file.Path;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
Expand Down Expand Up @@ -100,6 +101,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 @@ -1077,6 +1080,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()))) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we move SearchableSnapshotsConstants#SNAPSHOT_DIRECTORY_FACTORY_KEY and SearchableSnapshotsConstants#isSearchableSnapshotStore to server rather than just using the literal "snapshot" throughout? Either that or add an independent constant in server and then add a static constructor to o.e.x.c.searchablesnapshots.SearchableSnapshotsConstants to assert that the constant in server is equal to SNAPSHOT_DIRECTORY_FACTORY_KEY?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'll do something like this in a follow-up (it touches places outside of this pull request too)

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 @@ -1108,11 +1114,23 @@ 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, INDEX_NUMBER_OF_SHARDS_SETTING.get(targetIndexSettings));
}

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 @@ -1132,7 +1150,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,131 @@
/*
* 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 java.util.List;

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this annotation I think, this is automatically called since the annotation is on the parent?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least on my Intellij 2021.1.3 this is required for integ tests for JUnit to correctly set up the internal test cluster.

@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", List.of("index"));
assertAcked(client().admin().indices().prepareDelete("index"));
mountSnapshot("repository", "snapshot", "index", "mounted-index", Settings.EMPTY, randomFrom(Storage.values()));
ensureGreen("mounted-index");
}

@After
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for this annotation I think, this is automatically called since the annotation is on the parent?

@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(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: just assertEquals? (here and in other similar spots)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do prefer the error messages returned by assertThat than assertEquals, if that's ok.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah sure :) didn't even know they were different :D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm with Tanguy on this one, I find the argument order for assertEquals(expected, actual) confusing since it's the opposite to assertThat(actual, expectation).

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"));
}
}