mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-17 10:25:15 +00:00
Port most snapshot/restore static bwc tests to qa:full-cluster-restart (#25296)
Ports all of RepositoryUpgradabilityIT to qa:full-cluster-restart and ports as much of RestoreBackwardsCompatIT as possible into qa:full-cluster-restart.
This commit is contained in:
parent
bec1a49a54
commit
4bbb7e828b
@ -1,204 +0,0 @@
|
||||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.bwcompat;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.io.FileTestUtils;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.snapshots.AbstractSnapshotIntegTestCase;
|
||||
import org.elasticsearch.snapshots.SnapshotId;
|
||||
import org.elasticsearch.snapshots.SnapshotInfo;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
|
||||
/**
|
||||
* Tests that a repository can handle both snapshots of previous version formats and new version formats,
|
||||
* as blob names and repository blob formats have changed between the snapshot versions.
|
||||
*/
|
||||
@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST)
|
||||
// this test sometimes fails in recovery when the recovery is reset, increasing the logging level to help debug
|
||||
@TestLogging("org.elasticsearch.indices.recovery:DEBUG")
|
||||
public class RepositoryUpgradabilityIT extends AbstractSnapshotIntegTestCase {
|
||||
|
||||
/**
|
||||
* This tests that a repository can inter-operate with snapshots that both have and don't have a UUID,
|
||||
* namely when a repository was created in an older version with snapshots created in the old format
|
||||
* (only snapshot name, no UUID) and then the repository is loaded into newer versions where subsequent
|
||||
* snapshots have a name and a UUID.
|
||||
*/
|
||||
public void testRepositoryWorksWithCrossVersions() throws Exception {
|
||||
final List<String> repoVersions = listRepoVersions();
|
||||
// run the test for each supported version
|
||||
for (final String version : repoVersions) {
|
||||
final String repoName = "test-repo-" + version;
|
||||
logger.info("--> creating repository [{}] for version [{}]", repoName, version);
|
||||
createRepository(version, repoName);
|
||||
|
||||
logger.info("--> get the snapshots");
|
||||
final String originalIndex = "index-" + version;
|
||||
final Set<String> indices = Sets.newHashSet(originalIndex);
|
||||
final Set<SnapshotInfo> snapshotInfos = Sets.newHashSet(getSnapshots(repoName));
|
||||
assertThat(snapshotInfos.size(), equalTo(1));
|
||||
SnapshotInfo originalSnapshot = snapshotInfos.iterator().next();
|
||||
if (Version.fromString(version).before(Version.V_5_0_0_alpha1)) {
|
||||
assertThat(originalSnapshot.snapshotId(), equalTo(new SnapshotId("test_1", "test_1")));
|
||||
} else {
|
||||
assertThat(originalSnapshot.snapshotId().getName(), equalTo("test_1"));
|
||||
assertNotNull(originalSnapshot.snapshotId().getUUID()); // it's a random UUID now
|
||||
}
|
||||
assertThat(Sets.newHashSet(originalSnapshot.indices()), equalTo(indices));
|
||||
|
||||
logger.info("--> restore the original snapshot");
|
||||
final Set<String> restoredIndices = Sets.newHashSet(
|
||||
restoreSnapshot(repoName, originalSnapshot.snapshotId().getName())
|
||||
);
|
||||
assertThat(restoredIndices, equalTo(indices));
|
||||
// make sure it has documents
|
||||
for (final String searchIdx : restoredIndices) {
|
||||
assertThat(client().prepareSearch(searchIdx).setSize(0).get().getHits().getTotalHits(), greaterThan(0L));
|
||||
}
|
||||
deleteIndices(restoredIndices); // delete so we can restore again later
|
||||
|
||||
final String snapshotName2 = "test_2";
|
||||
logger.info("--> take a new snapshot of the old index");
|
||||
final int addedDocSize = 10;
|
||||
for (int i = 0; i < addedDocSize; i++) {
|
||||
index(originalIndex, "doc", Integer.toString(i), "foo", "new-bar-" + i);
|
||||
}
|
||||
refresh();
|
||||
snapshotInfos.add(createSnapshot(repoName, snapshotName2));
|
||||
|
||||
logger.info("--> get the snapshots with the newly created snapshot [{}]", snapshotName2);
|
||||
Set<SnapshotInfo> snapshotInfosFromRepo = Sets.newHashSet(getSnapshots(repoName));
|
||||
assertThat(snapshotInfosFromRepo, equalTo(snapshotInfos));
|
||||
snapshotInfosFromRepo.forEach(snapshotInfo -> {
|
||||
assertThat(Sets.newHashSet(snapshotInfo.indices()), equalTo(indices));
|
||||
});
|
||||
|
||||
final String snapshotName3 = "test_3";
|
||||
final String indexName2 = "index2";
|
||||
logger.info("--> take a new snapshot with a new index");
|
||||
createIndex(indexName2);
|
||||
indices.add(indexName2);
|
||||
for (int i = 0; i < addedDocSize; i++) {
|
||||
index(indexName2, "doc", Integer.toString(i), "foo", "new-bar-" + i);
|
||||
}
|
||||
refresh();
|
||||
snapshotInfos.add(createSnapshot(repoName, snapshotName3));
|
||||
|
||||
logger.info("--> get the snapshots with the newly created snapshot [{}]", snapshotName3);
|
||||
snapshotInfosFromRepo = Sets.newHashSet(getSnapshots(repoName));
|
||||
assertThat(snapshotInfosFromRepo, equalTo(snapshotInfos));
|
||||
snapshotInfosFromRepo.forEach(snapshotInfo -> {
|
||||
if (snapshotInfo.snapshotId().getName().equals(snapshotName3)) {
|
||||
// only the last snapshot has all the indices
|
||||
assertThat(Sets.newHashSet(snapshotInfo.indices()), equalTo(indices));
|
||||
} else {
|
||||
assertThat(Sets.newHashSet(snapshotInfo.indices()), equalTo(Sets.newHashSet(originalIndex)));
|
||||
}
|
||||
});
|
||||
deleteIndices(indices); // clean up indices
|
||||
|
||||
logger.info("--> restore the old snapshot again");
|
||||
Set<String> oldRestoredIndices = Sets.newHashSet(restoreSnapshot(repoName, originalSnapshot.snapshotId().getName()));
|
||||
assertThat(oldRestoredIndices, equalTo(Sets.newHashSet(originalIndex)));
|
||||
for (final String searchIdx : oldRestoredIndices) {
|
||||
assertThat(client().prepareSearch(searchIdx).setSize(0).get().getHits().getTotalHits(),
|
||||
greaterThanOrEqualTo((long)addedDocSize));
|
||||
}
|
||||
deleteIndices(oldRestoredIndices);
|
||||
|
||||
logger.info("--> restore the new snapshot");
|
||||
Set<String> newSnapshotIndices = Sets.newHashSet(restoreSnapshot(repoName, snapshotName3));
|
||||
assertThat(newSnapshotIndices, equalTo(Sets.newHashSet(originalIndex, indexName2)));
|
||||
for (final String searchIdx : newSnapshotIndices) {
|
||||
assertThat(client().prepareSearch(searchIdx).setSize(0).get().getHits().getTotalHits(),
|
||||
greaterThanOrEqualTo((long)addedDocSize));
|
||||
}
|
||||
deleteIndices(newSnapshotIndices); // clean up indices before starting again
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> listRepoVersions() throws Exception {
|
||||
final String prefix = "repo";
|
||||
final List<String> repoVersions = new ArrayList<>();
|
||||
final Path repoFiles = getBwcIndicesPath();
|
||||
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(repoFiles, prefix + "-*.zip")) {
|
||||
for (final Path entry : dirStream) {
|
||||
final String fileName = entry.getFileName().toString();
|
||||
String version = fileName.substring(prefix.length() + 1);
|
||||
version = version.substring(0, version.length() - ".zip".length());
|
||||
repoVersions.add(version);
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableList(repoVersions);
|
||||
}
|
||||
|
||||
private void createRepository(final String version, final String repoName) throws Exception {
|
||||
final String prefix = "repo";
|
||||
final Path repoFile = getBwcIndicesPath().resolve(prefix + "-" + version + ".zip");
|
||||
final Path repoPath = randomRepoPath();
|
||||
FileTestUtils.unzip(repoFile, repoPath, "repo/");
|
||||
assertAcked(client().admin().cluster().preparePutRepository(repoName)
|
||||
.setType("fs")
|
||||
.setSettings(Settings.builder().put("location", repoPath)));
|
||||
}
|
||||
|
||||
private List<SnapshotInfo> getSnapshots(final String repoName) throws Exception {
|
||||
return client().admin().cluster().prepareGetSnapshots(repoName)
|
||||
.addSnapshots("_all")
|
||||
.get()
|
||||
.getSnapshots();
|
||||
}
|
||||
|
||||
private SnapshotInfo createSnapshot(final String repoName, final String snapshotName) throws Exception {
|
||||
return client().admin().cluster().prepareCreateSnapshot(repoName, snapshotName)
|
||||
.setWaitForCompletion(true)
|
||||
.get()
|
||||
.getSnapshotInfo();
|
||||
}
|
||||
|
||||
private List<String> restoreSnapshot(final String repoName, final String snapshotName) throws Exception {
|
||||
return client().admin().cluster().prepareRestoreSnapshot(repoName, snapshotName)
|
||||
.setWaitForCompletion(true)
|
||||
.get()
|
||||
.getRestoreInfo()
|
||||
.indices();
|
||||
}
|
||||
|
||||
private void deleteIndices(final Set<String> indices) throws Exception {
|
||||
client().admin().indices().prepareDelete(indices.toArray(new String[indices.size()])).get();
|
||||
}
|
||||
|
||||
}
|
@ -18,27 +18,15 @@
|
||||
*/
|
||||
package org.elasticsearch.bwcompat;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsResponse;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
|
||||
import org.elasticsearch.cluster.routing.allocation.decider.FilterAllocationDecider;
|
||||
import org.elasticsearch.common.io.FileTestUtils;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.repositories.fs.FsRepository;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.snapshots.AbstractSnapshotIntegTestCase;
|
||||
import org.elasticsearch.snapshots.RestoreInfo;
|
||||
import org.elasticsearch.snapshots.SnapshotInfo;
|
||||
import org.elasticsearch.snapshots.SnapshotRestoreException;
|
||||
import org.elasticsearch.snapshots.mockstore.MockRepository;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.test.ESIntegTestCase.Scope;
|
||||
import org.elasticsearch.test.VersionUtils;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -46,19 +34,15 @@ import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
import static org.hamcrest.Matchers.anyOf;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
/**
|
||||
* Tests that restoring from a very old snapshot fails appropriately.
|
||||
*/
|
||||
@ClusterScope(scope = Scope.TEST)
|
||||
public class RestoreBackwardsCompatIT extends AbstractSnapshotIntegTestCase {
|
||||
|
||||
@ -77,40 +61,6 @@ public class RestoreBackwardsCompatIT extends AbstractSnapshotIntegTestCase {
|
||||
repoPath = createTempDir("repositories");
|
||||
}
|
||||
|
||||
public void testRestoreOldSnapshots() throws Exception {
|
||||
String repo = "test_repo";
|
||||
String snapshot = "test_1";
|
||||
List<String> repoVersions = repoVersions();
|
||||
assertThat(repoVersions.size(), greaterThan(0));
|
||||
for (String version : repoVersions) {
|
||||
createRepo("repo", version, repo);
|
||||
testOldSnapshot(version, repo, snapshot);
|
||||
}
|
||||
|
||||
SortedSet<String> expectedVersions = new TreeSet<>();
|
||||
for (Version v : VersionUtils.allReleasedVersions()) {
|
||||
// The current version is in the "released" list even though it isn't released for historical reasons
|
||||
if (v == Version.CURRENT) continue;
|
||||
if (v.isRelease() == false) continue; // no guarantees for prereleases
|
||||
if (v.before(Version.CURRENT.minimumIndexCompatibilityVersion())) continue; // we only support versions N and N-1
|
||||
if (v.equals(Version.CURRENT)) continue; // the current version is always compatible with itself
|
||||
expectedVersions.add(v.toString());
|
||||
}
|
||||
|
||||
for (String repoVersion : repoVersions) {
|
||||
if (expectedVersions.remove(repoVersion) == false) {
|
||||
logger.warn("Old repositories tests contain extra repo: {}", repoVersion);
|
||||
}
|
||||
}
|
||||
if (expectedVersions.isEmpty() == false) {
|
||||
StringBuilder msg = new StringBuilder("Old repositories tests are missing versions:");
|
||||
for (String expected : expectedVersions) {
|
||||
msg.append("\n" + expected);
|
||||
}
|
||||
fail(msg.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void testRestoreUnsupportedSnapshots() throws Exception {
|
||||
String repo = "test_repo";
|
||||
String snapshot = "test_1";
|
||||
@ -122,10 +72,6 @@ public class RestoreBackwardsCompatIT extends AbstractSnapshotIntegTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> repoVersions() throws Exception {
|
||||
return listRepoVersions("repo");
|
||||
}
|
||||
|
||||
private List<String> unsupportedRepoVersions() throws Exception {
|
||||
return listRepoVersions("unsupportedrepo");
|
||||
}
|
||||
@ -155,65 +101,6 @@ public class RestoreBackwardsCompatIT extends AbstractSnapshotIntegTestCase {
|
||||
.put(FsRepository.REPOSITORIES_LOCATION_SETTING.getKey(), fsRepoPath.getParent().relativize(fsRepoPath).resolve("repo").toString())));
|
||||
}
|
||||
|
||||
private void testOldSnapshot(String version, String repo, String snapshot) throws IOException {
|
||||
logger.info("--> get snapshot and check its version");
|
||||
GetSnapshotsResponse getSnapshotsResponse = client().admin().cluster().prepareGetSnapshots(repo).setSnapshots(snapshot).get();
|
||||
assertThat(getSnapshotsResponse.getSnapshots().size(), equalTo(1));
|
||||
SnapshotInfo snapshotInfo = getSnapshotsResponse.getSnapshots().get(0);
|
||||
assertThat(snapshotInfo.version().toString(), equalTo(version));
|
||||
|
||||
logger.info("--> get less verbose snapshot info");
|
||||
getSnapshotsResponse = client().admin().cluster().prepareGetSnapshots(repo)
|
||||
.setSnapshots(snapshot).setVerbose(false).get();
|
||||
assertEquals(1, getSnapshotsResponse.getSnapshots().size());
|
||||
snapshotInfo = getSnapshotsResponse.getSnapshots().get(0);
|
||||
assertEquals(snapshot, snapshotInfo.snapshotId().getName());
|
||||
assertNull(snapshotInfo.version()); // in verbose=false mode, version doesn't exist
|
||||
|
||||
logger.info("--> restoring snapshot");
|
||||
RestoreSnapshotResponse response = client().admin().cluster().prepareRestoreSnapshot(repo, snapshot).setRestoreGlobalState(true).setWaitForCompletion(true).get();
|
||||
assertThat(response.status(), equalTo(RestStatus.OK));
|
||||
RestoreInfo restoreInfo = response.getRestoreInfo();
|
||||
assertThat(restoreInfo.successfulShards(), greaterThan(0));
|
||||
assertThat(restoreInfo.successfulShards(), equalTo(restoreInfo.totalShards()));
|
||||
assertThat(restoreInfo.failedShards(), equalTo(0));
|
||||
String index = restoreInfo.indices().get(0);
|
||||
|
||||
logger.info("--> check search");
|
||||
SearchResponse searchResponse = client().prepareSearch(index).get();
|
||||
assertThat(searchResponse.getHits().getTotalHits(), greaterThan(1L));
|
||||
|
||||
logger.info("--> check settings");
|
||||
ClusterState clusterState = client().admin().cluster().prepareState().get().getState();
|
||||
assertThat(clusterState.metaData().persistentSettings().get(FilterAllocationDecider.CLUSTER_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + "version_attr"), equalTo(version));
|
||||
|
||||
logger.info("--> check templates");
|
||||
IndexTemplateMetaData template = clusterState.getMetaData().templates().get("template_" + version.toLowerCase(Locale.ROOT));
|
||||
assertThat(template, notNullValue());
|
||||
assertThat(template.patterns(), equalTo(Collections.singletonList("te*")));
|
||||
assertThat(template.settings().getAsInt(IndexMetaData.SETTING_NUMBER_OF_SHARDS, -1), equalTo(1));
|
||||
assertThat(template.mappings().size(), equalTo(1));
|
||||
assertThat(template.mappings().get("type1").string(),
|
||||
anyOf(
|
||||
equalTo("{\"type1\":{\"_source\":{\"enabled\":false}}}"),
|
||||
equalTo("{\"type1\":{\"_source\":{\"enabled\":\"false\"}}}"),
|
||||
equalTo("{\"type1\":{\"_source\":{\"enabled\":\"0\"}}}"),
|
||||
equalTo("{\"type1\":{\"_source\":{\"enabled\":0}}}"),
|
||||
equalTo("{\"type1\":{\"_source\":{\"enabled\":\"off\"}}}"),
|
||||
equalTo("{\"type1\":{\"_source\":{\"enabled\":\"no\"}}}")
|
||||
));
|
||||
assertThat(template.aliases().size(), equalTo(3));
|
||||
assertThat(template.aliases().get("alias1"), notNullValue());
|
||||
assertThat(template.aliases().get("alias2").filter().string(), containsString(version));
|
||||
assertThat(template.aliases().get("alias2").indexRouting(), equalTo("kimchy"));
|
||||
assertThat(template.aliases().get("{index}-alias"), notNullValue());
|
||||
|
||||
logger.info("--> cleanup");
|
||||
cluster().wipeIndices(restoreInfo.indices().toArray(new String[restoreInfo.indices().size()]));
|
||||
cluster().wipeTemplates();
|
||||
|
||||
}
|
||||
|
||||
private void assertUnsupportedIndexFailsToRestore(String repo, String snapshot) throws IOException {
|
||||
logger.info("--> restoring unsupported snapshot");
|
||||
try {
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package org.elasticsearch.upgrades;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
@ -30,6 +31,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.common.xcontent.support.XContentMapValues;
|
||||
import org.elasticsearch.test.NotEqualMessageBuilder;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.junit.Before;
|
||||
|
||||
@ -85,6 +87,11 @@ public class FullClusterRestartIT extends ESRestTestCase {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean preserveTemplatesUponCompletion() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void testSearch() throws Exception {
|
||||
int count;
|
||||
if (runningAgainstOldCluster) {
|
||||
@ -328,7 +335,7 @@ public class FullClusterRestartIT extends ESRestTestCase {
|
||||
assertNoFailures(searchRsp);
|
||||
int totalHits = (int) XContentMapValues.extractValue("hits.total", searchRsp);
|
||||
assertEquals(count, totalHits);
|
||||
Map<?, ?> bestHit = (Map<?, ?>) ((List)(XContentMapValues.extractValue("hits.hits", searchRsp))).get(0);
|
||||
Map<?, ?> bestHit = (Map<?, ?>) ((List<?>)(XContentMapValues.extractValue("hits.hits", searchRsp))).get(0);
|
||||
|
||||
// Make sure there are payloads and they are taken into account for the score
|
||||
// the 'string' field has a boost of 4 in the mappings so it should get a payload boost
|
||||
@ -387,7 +394,7 @@ public class FullClusterRestartIT extends ESRestTestCase {
|
||||
requestBody = "{ \"query\": { \"match_all\" : {} }}";
|
||||
Map<String, Object> searchRsp = toMap(client().performRequest("GET", "/" + index + "/_search", Collections.emptyMap(),
|
||||
new StringEntity(requestBody, ContentType.APPLICATION_JSON)));
|
||||
Map<?, ?> hit = (Map<?, ?>) ((List)(XContentMapValues.extractValue("hits.hits", searchRsp))).get(0);
|
||||
Map<?, ?> hit = (Map<?, ?>) ((List<?>)(XContentMapValues.extractValue("hits.hits", searchRsp))).get(0);
|
||||
String docId = (String) hit.get("_id");
|
||||
|
||||
requestBody = "{ \"doc\" : { \"foo\": \"bar\"}}";
|
||||
@ -596,13 +603,74 @@ public class FullClusterRestartIT extends ESRestTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests snapshot/restore by creating a snapshot and restoring it. It takes
|
||||
* a snapshot on the old cluster and restores it on the old cluster as a
|
||||
* sanity check and on the new cluster as an upgrade test. It also takes a
|
||||
* snapshot on the new cluster and restores that on the new cluster as a
|
||||
* test that the repository is ok with containing snapshot from both the
|
||||
* old and new versions. All of the snapshots include an index, a template,
|
||||
* and some routing configuration.
|
||||
*/
|
||||
public void testSnapshotRestore() throws IOException {
|
||||
int count;
|
||||
if (runningAgainstOldCluster) {
|
||||
// Create the index
|
||||
count = between(200, 300);
|
||||
indexRandomDocuments(count, true, true, i -> jsonBuilder().startObject().field("field", "value").endObject());
|
||||
} else {
|
||||
count = countOfIndexedRandomDocuments();
|
||||
}
|
||||
|
||||
// Create the repo and the snapshot
|
||||
// Refresh the index so the count doesn't fail
|
||||
refresh();
|
||||
|
||||
// Count the documents in the index to make sure we have as many as we put there
|
||||
String countResponse = toStr(client().performRequest("GET", "/" + index + "/_search", singletonMap("size", "0")));
|
||||
assertThat(countResponse, containsString("\"total\":" + count));
|
||||
|
||||
// Stick a routing attribute into to cluster settings so we can see it after the restore
|
||||
HttpEntity routingSetting = new StringEntity(
|
||||
"{\"persistent\": {\"cluster.routing.allocation.exclude.test_attr\": \"" + oldClusterVersion + "\"}}",
|
||||
ContentType.APPLICATION_JSON);
|
||||
client().performRequest("PUT", "/_cluster/settings", emptyMap(), routingSetting);
|
||||
|
||||
// Stick a template into the cluster so we can see it after the restore
|
||||
XContentBuilder templateBuilder = JsonXContent.contentBuilder().startObject();
|
||||
templateBuilder.field("template", "evil_*"); // Don't confuse other tests by applying the template
|
||||
templateBuilder.startObject("settings"); {
|
||||
templateBuilder.field("number_of_shards", 1);
|
||||
}
|
||||
templateBuilder.endObject();
|
||||
templateBuilder.startObject("mappings"); {
|
||||
templateBuilder.startObject("doc"); {
|
||||
templateBuilder.startObject("_source"); {
|
||||
templateBuilder.field("enabled", true);
|
||||
}
|
||||
templateBuilder.endObject();
|
||||
}
|
||||
templateBuilder.endObject();
|
||||
}
|
||||
templateBuilder.endObject();
|
||||
templateBuilder.startObject("aliases"); {
|
||||
templateBuilder.startObject("alias1").endObject();
|
||||
templateBuilder.startObject("alias2"); {
|
||||
templateBuilder.startObject("filter"); {
|
||||
templateBuilder.startObject("term"); {
|
||||
templateBuilder.field("version", runningAgainstOldCluster ? oldClusterVersion : Version.CURRENT);
|
||||
}
|
||||
templateBuilder.endObject();
|
||||
}
|
||||
templateBuilder.endObject();
|
||||
}
|
||||
templateBuilder.endObject();
|
||||
}
|
||||
templateBuilder.endObject().endObject();
|
||||
client().performRequest("PUT", "/_template/test_template", emptyMap(),
|
||||
new StringEntity(templateBuilder.string(), ContentType.APPLICATION_JSON));
|
||||
|
||||
if (runningAgainstOldCluster) {
|
||||
// Create the repo
|
||||
XContentBuilder repoConfig = JsonXContent.contentBuilder().startObject(); {
|
||||
repoConfig.field("type", "fs");
|
||||
repoConfig.startObject("settings"); {
|
||||
@ -614,58 +682,110 @@ public class FullClusterRestartIT extends ESRestTestCase {
|
||||
repoConfig.endObject();
|
||||
client().performRequest("PUT", "/_snapshot/repo", emptyMap(),
|
||||
new StringEntity(repoConfig.string(), ContentType.APPLICATION_JSON));
|
||||
|
||||
XContentBuilder snapshotConfig = JsonXContent.contentBuilder().startObject(); {
|
||||
snapshotConfig.field("indices", index);
|
||||
}
|
||||
snapshotConfig.endObject();
|
||||
client().performRequest("PUT", "/_snapshot/repo/snap", singletonMap("wait_for_completion", "true"),
|
||||
new StringEntity(snapshotConfig.string(), ContentType.APPLICATION_JSON));
|
||||
|
||||
// Refresh the index so the count doesn't fail
|
||||
refresh();
|
||||
} else {
|
||||
count = countOfIndexedRandomDocuments();
|
||||
}
|
||||
|
||||
// Count the documents in the index to make sure we have as many as we put there
|
||||
String countResponse = toStr(client().performRequest("GET", "/" + index + "/_search", singletonMap("size", "0")));
|
||||
assertThat(countResponse, containsString("\"total\":" + count));
|
||||
client().performRequest("PUT", "/_snapshot/repo/" + (runningAgainstOldCluster ? "old_snap" : "new_snap"),
|
||||
singletonMap("wait_for_completion", "true"),
|
||||
new StringEntity("{\"indices\": \"" + index + "\"}", ContentType.APPLICATION_JSON));
|
||||
|
||||
checkSnapshot("old_snap", count, oldClusterVersion);
|
||||
if (false == runningAgainstOldCluster) {
|
||||
/* Remove any "restored" indices from the old cluster run of this test.
|
||||
* We intentionally don't remove them while running this against the
|
||||
* old cluster so we can test starting the node with a restored index
|
||||
* in the cluster. */
|
||||
client().performRequest("DELETE", "/restored_*");
|
||||
checkSnapshot("new_snap", count, Version.CURRENT);
|
||||
}
|
||||
}
|
||||
|
||||
// Check the metadata, especially the version
|
||||
Map<String, String> params;
|
||||
if (oldClusterVersion.onOrAfter(Version.V_5_5_0)) {
|
||||
params = singletonMap("verbose", "true");
|
||||
} else {
|
||||
params = Collections.emptyMap();
|
||||
}
|
||||
String response = toStr(client().performRequest("GET", "/_snapshot/repo/_all", params));
|
||||
private void checkSnapshot(String snapshotName, int count, Version tookOnVersion) throws IOException {
|
||||
// Check the snapshot metadata, especially the version
|
||||
String response = toStr(client().performRequest("GET", "/_snapshot/repo/" + snapshotName, listSnapshotVerboseParams()));
|
||||
Map<String, Object> map = toMap(response);
|
||||
assertEquals(response, singletonList("snap"), XContentMapValues.extractValue("snapshots.snapshot", map));
|
||||
assertEquals(response, singletonList(snapshotName), XContentMapValues.extractValue("snapshots.snapshot", map));
|
||||
assertEquals(response, singletonList("SUCCESS"), XContentMapValues.extractValue("snapshots.state", map));
|
||||
assertEquals(response, singletonList(oldClusterVersion.toString()), XContentMapValues.extractValue("snapshots.version", map));
|
||||
assertEquals(response, singletonList(tookOnVersion.toString()), XContentMapValues.extractValue("snapshots.version", map));
|
||||
|
||||
// Remove the routing setting and template so we can test restoring them.
|
||||
HttpEntity clearRoutingSetting = new StringEntity(
|
||||
"{\"persistent\":{\"cluster.routing.allocation.exclude.test_attr\": null}}",
|
||||
ContentType.APPLICATION_JSON);
|
||||
client().performRequest("PUT", "/_cluster/settings", emptyMap(), clearRoutingSetting);
|
||||
client().performRequest("DELETE", "/_template/test_template", emptyMap(), clearRoutingSetting);
|
||||
|
||||
// Restore
|
||||
XContentBuilder restoreCommand = JsonXContent.contentBuilder().startObject();
|
||||
restoreCommand.field("include_global_state", randomBoolean());
|
||||
restoreCommand.field("include_global_state", true);
|
||||
restoreCommand.field("indices", index);
|
||||
restoreCommand.field("rename_pattern", index);
|
||||
restoreCommand.field("rename_replacement", "restored_" + index);
|
||||
restoreCommand.endObject();
|
||||
client().performRequest("POST", "/_snapshot/repo/snap/_restore", singletonMap("wait_for_completion", "true"),
|
||||
client().performRequest("POST", "/_snapshot/repo/" + snapshotName + "/_restore", singletonMap("wait_for_completion", "true"),
|
||||
new StringEntity(restoreCommand.string(), ContentType.APPLICATION_JSON));
|
||||
|
||||
countResponse = toStr(
|
||||
client().performRequest("GET", "/restored_" + index + "/_search", singletonMap("size", "0")));
|
||||
assertThat(countResponse, containsString("\"total\":" + count));
|
||||
// Make sure search finds all documents
|
||||
String countResponse = toStr(client().performRequest("GET", "/restored_" + index + "/_search", singletonMap("size", "0")));
|
||||
assertThat(countResponse, containsString("\"total\":" + count));
|
||||
|
||||
// Add some extra documents to the index to be sure we can still write to it after restoring it
|
||||
int extras = between(1, 100);
|
||||
StringBuilder bulk = new StringBuilder();
|
||||
for (int i = 0; i < extras; i++) {
|
||||
bulk.append("{\"index\":{\"_id\":\"").append(count + i).append("\"}}\n");
|
||||
bulk.append("{\"test\":\"test\"}\n");
|
||||
}
|
||||
client().performRequest("POST", "/restored_" + index + "/doc/_bulk", singletonMap("refresh", "true"),
|
||||
new StringEntity(bulk.toString(), ContentType.APPLICATION_JSON));
|
||||
|
||||
// And count to make sure the add worked
|
||||
// Make sure search finds all documents
|
||||
countResponse = toStr(client().performRequest("GET", "/restored_" + index + "/_search", singletonMap("size", "0")));
|
||||
assertThat(countResponse, containsString("\"total\":" + (count + extras)));
|
||||
|
||||
// Clean up the index for the next iteration
|
||||
client().performRequest("DELETE", "/restored_*");
|
||||
|
||||
// Check settings added by the restore process
|
||||
map = toMap(client().performRequest("GET", "/_cluster/settings", singletonMap("flat_settings", "true")));
|
||||
Map<String, Object> expected = new HashMap<>();
|
||||
expected.put("transient", emptyMap());
|
||||
expected.put("persistent", singletonMap("cluster.routing.allocation.exclude.test_attr", oldClusterVersion.toString()));
|
||||
if (expected.equals(map) == false) {
|
||||
NotEqualMessageBuilder builder = new NotEqualMessageBuilder();
|
||||
builder.compareMaps(map, expected);
|
||||
fail("settings don't match:\n" + builder.toString());
|
||||
}
|
||||
|
||||
// Check that the template was restored successfully
|
||||
map = toMap(client().performRequest("GET", "/_template/test_template"));
|
||||
expected = new HashMap<>();
|
||||
if (runningAgainstOldCluster) {
|
||||
expected.put("template", "evil_*");
|
||||
} else {
|
||||
expected.put("index_patterns", singletonList("evil_*"));
|
||||
}
|
||||
expected.put("settings", singletonMap("index", singletonMap("number_of_shards", "1")));
|
||||
expected.put("mappings", singletonMap("doc", singletonMap("_source", singletonMap("enabled", true))));
|
||||
expected.put("order", 0);
|
||||
Map<String, Object> aliases = new HashMap<>();
|
||||
aliases.put("alias1", emptyMap());
|
||||
aliases.put("alias2", singletonMap("filter", singletonMap("term", singletonMap("version", tookOnVersion.toString()))));
|
||||
expected.put("aliases", aliases);
|
||||
expected = singletonMap("test_template", expected);
|
||||
if (false == expected.equals(map)) {
|
||||
NotEqualMessageBuilder builder = new NotEqualMessageBuilder();
|
||||
builder.compareMaps(map, expected);
|
||||
fail("template doesn't match:\n" + builder.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters required to get the version of Elasticsearch that took the snapshot.
|
||||
* On versions after 5.5 we need a {@code verbose} parameter.
|
||||
*/
|
||||
private Map<String, String> listSnapshotVerboseParams() {
|
||||
if (runningAgainstOldCluster && oldClusterVersion.before(Version.V_5_5_0)) {
|
||||
return emptyMap();
|
||||
}
|
||||
return singletonMap("verbose", "true");
|
||||
}
|
||||
|
||||
// TODO tests for upgrades after shrink. We've had trouble with shrink in the past.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user