Skip to content

Commit 07395f3

Browse files
authored
Rewrite SnapshotLifecycleIT as as ESIntegTestCase (#46356)
* Rewrite SnapshotLifecycleIT as as ESIntegTestCase This commit splits `SnapshotLifecycleIT` into two different tests. `SnapshotLifecycleRestIT` which includes the tests that do not require slow repositories, and `SLMSnapshotBlockingIntegTests` which is now an integration test using `MockRepository` to simulate a snapshot being in progress. Relates to #43663 Resolves #46205 * Add error logging when exceptions are thrown
1 parent 5eead86 commit 07395f3

File tree

6 files changed

+302
-187
lines changed

6 files changed

+302
-187
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/slm/SnapshotLifecyclePolicyItem.java

+16
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,22 @@ public static SnapshotInProgress fromEntry(SnapshotsInProgress.Entry entry) {
211211
entry.state(), entry.startTime(), entry.failure());
212212
}
213213

214+
public SnapshotId getSnapshotId() {
215+
return snapshotId;
216+
}
217+
218+
public SnapshotsInProgress.State getState() {
219+
return state;
220+
}
221+
222+
public long getStartTime() {
223+
return startTime;
224+
}
225+
226+
public String getFailure() {
227+
return failure;
228+
}
229+
214230
@Override
215231
public void writeTo(StreamOutput out) throws IOException {
216232
this.snapshotId.writeTo(out);

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/slm/action/GetSnapshotLifecycleAction.java

+4
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@ public Response(StreamInput in) throws IOException {
9494
this.lifecycles = in.readList(SnapshotLifecyclePolicyItem::new);
9595
}
9696

97+
public List<SnapshotLifecyclePolicyItem> getPolicies() {
98+
return this.lifecycles;
99+
}
100+
97101
@Override
98102
public String toString() {
99103
return Strings.toString(this);

x-pack/plugin/ilm/build.gradle

-1
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,3 @@ gradle.projectsEvaluated {
3030
}
3131

3232
integTest.enabled = false
33-

x-pack/plugin/ilm/qa/multi-node/build.gradle

-4
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,4 @@ testClusters.integTest {
2525
setting 'xpack.ml.enabled', 'false'
2626
setting 'xpack.license.self_generated.type', 'trial'
2727
setting 'indices.lifecycle.poll_interval', '1000ms'
28-
// TODO: Find a way to run these tests with more than one snapshot pool thread. Currently we need to limit to one thread so that the
29-
// rate limiting settings in SnapshotLifecycleIT doesn't result in blocked snapshot threads because multiple threads overshoot
30-
// the limit simultaneously and the rate limiter then moves to wait minutes to make up for this.
31-
setting 'thread_pool.snapshot.max', '1'
3228
}

x-pack/plugin/ilm/qa/multi-node/src/test/java/org/elasticsearch/xpack/slm/SnapshotLifecycleIT.java renamed to x-pack/plugin/ilm/qa/multi-node/src/test/java/org/elasticsearch/xpack/slm/SnapshotLifecycleRestIT.java

+1-182
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
import org.apache.http.util.EntityUtils;
1010
import org.elasticsearch.ElasticsearchException;
1111
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
12-
import org.apache.lucene.util.LuceneTestCase.AwaitsFix;
1312
import org.elasticsearch.action.index.IndexRequestBuilder;
1413
import org.elasticsearch.client.Request;
1514
import org.elasticsearch.client.Response;
@@ -41,23 +40,20 @@
4140
import java.util.HashMap;
4241
import java.util.List;
4342
import java.util.Map;
44-
import java.util.Optional;
4543
import java.util.concurrent.TimeUnit;
4644

4745
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
4846
import static org.elasticsearch.xpack.core.slm.history.SnapshotHistoryItem.CREATE_OPERATION;
4947
import static org.elasticsearch.xpack.core.slm.history.SnapshotHistoryItem.DELETE_OPERATION;
5048
import static org.elasticsearch.xpack.core.slm.history.SnapshotHistoryStore.SLM_HISTORY_INDEX_PREFIX;
5149
import static org.elasticsearch.xpack.ilm.TimeSeriesLifecycleActionsIT.getStepKeyForIndex;
52-
import static org.hamcrest.Matchers.anyOf;
5350
import static org.hamcrest.Matchers.containsString;
5451
import static org.hamcrest.Matchers.equalTo;
5552
import static org.hamcrest.Matchers.greaterThan;
5653
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
5754
import static org.hamcrest.Matchers.startsWith;
5855

59-
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/pull/46205")
60-
public class SnapshotLifecycleIT extends ESRestTestCase {
56+
public class SnapshotLifecycleRestIT extends ESRestTestCase {
6157

6258
@Override
6359
protected boolean waitForAllSnapshotsWiped() {
@@ -335,183 +331,6 @@ public void testBasicTimeBasedRetenion() throws Exception {
335331
}
336332
}
337333

338-
@SuppressWarnings("unchecked")
339-
public void testSnapshotInProgress() throws Exception {
340-
final String indexName = "test";
341-
final String policyName = "test-policy";
342-
final String repoId = "my-repo";
343-
int docCount = 20;
344-
for (int i = 0; i < docCount; i++) {
345-
index(client(), indexName, "" + i, "foo", "bar");
346-
}
347-
348-
// Create a snapshot repo
349-
initializeRepo(repoId, "1b");
350-
351-
createSnapshotPolicy(policyName, "snap", "1 2 3 4 5 ?", repoId, indexName, true);
352-
353-
Response executeRepsonse = client().performRequest(new Request("PUT", "/_slm/policy/" + policyName + "/_execute"));
354-
355-
try (XContentParser parser = JsonXContent.jsonXContent.createParser(NamedXContentRegistry.EMPTY,
356-
DeprecationHandler.THROW_UNSUPPORTED_OPERATION, EntityUtils.toByteArray(executeRepsonse.getEntity()))) {
357-
final String snapshotName = parser.mapStrings().get("snapshot_name");
358-
359-
// Check that the executed snapshot shows up in the SLM output
360-
assertBusy(() -> {
361-
try {
362-
Response response = client().performRequest(new Request("GET", "/_slm/policy" + (randomBoolean() ? "" : "?human")));
363-
Map<String, Object> policyResponseMap;
364-
try (InputStream content = response.getEntity().getContent()) {
365-
policyResponseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), content, true);
366-
}
367-
assertThat(policyResponseMap.size(), greaterThan(0));
368-
Optional<Map<String, Object>> inProgress = Optional.ofNullable((Map<String, Object>) policyResponseMap.get(policyName))
369-
.map(policy -> (Map<String, Object>) policy.get("in_progress"));
370-
371-
if (inProgress.isPresent()) {
372-
Map<String, Object> inProgressMap = inProgress.get();
373-
assertThat(inProgressMap.get("name"), equalTo(snapshotName));
374-
assertNotNull(inProgressMap.get("uuid"));
375-
assertThat(inProgressMap.get("state"), equalTo("STARTED"));
376-
assertThat((long) inProgressMap.get("start_time_millis"), greaterThan(0L));
377-
assertNull(inProgressMap.get("failure"));
378-
} else {
379-
fail("expected in_progress to contain a running snapshot, but the response was " + policyResponseMap);
380-
}
381-
} catch (ResponseException e) {
382-
fail("expected policy to exist but it does not: " + EntityUtils.toString(e.getResponse().getEntity()));
383-
}
384-
});
385-
386-
// Cancel the snapshot since it is not going to complete quickly
387-
try {
388-
client().performRequest(new Request("DELETE", "/_snapshot/" + repoId + "/" + snapshotName));
389-
} catch (Exception e) {
390-
// ignore
391-
}
392-
}
393-
}
394-
395-
@SuppressWarnings("unchecked")
396-
public void testRetentionWhileSnapshotInProgress() throws Exception {
397-
final String indexName = "test";
398-
final String slowPolicy = "slow";
399-
final String fastPolicy = "fast";
400-
final String slowRepo = "slow-repo";
401-
final String fastRepo = "fast-repo";
402-
int docCount = 20;
403-
for (int i = 0; i < docCount; i++) {
404-
index(client(), indexName, "" + i, "foo", "bar");
405-
}
406-
407-
// Create snapshot repos, one fast and one slow
408-
initializeRepo(slowRepo, "1b");
409-
initializeRepo(fastRepo, "10mb");
410-
411-
createSnapshotPolicy(slowPolicy, "slow-snap", "1 2 3 4 5 ?", slowRepo, indexName, true,
412-
new SnapshotRetentionConfiguration(TimeValue.timeValueSeconds(0), null, null));
413-
createSnapshotPolicy(fastPolicy, "fast-snap", "1 2 3 4 5 ?", fastRepo, indexName, true,
414-
new SnapshotRetentionConfiguration(TimeValue.timeValueSeconds(0), null, null));
415-
416-
// Create a snapshot and wait for it to be complete (need something that can be deleted)
417-
final String completedSnapshotName = executePolicy(fastPolicy);
418-
assertBusy(() -> {
419-
try {
420-
Response getResp = client().performRequest(new Request("GET",
421-
"/_snapshot/" + fastRepo + "/" + completedSnapshotName + "/_status"));
422-
try (InputStream content = getResp.getEntity().getContent()) {
423-
Map<String, Object> snaps = XContentHelper.convertToMap(XContentType.JSON.xContent(), content, true);
424-
logger.info("--> waiting for snapshot {} to be successful, got: {}", completedSnapshotName, snaps);
425-
List<Map<String, Object>> snaps2 = (List<Map<String, Object>>) snaps.get("snapshots");
426-
assertThat(snaps2.get(0).get("state"), equalTo("SUCCESS"));
427-
428-
// Check that no in_progress snapshots show up
429-
Response response = client().performRequest(new Request("GET", "/_slm/policy"));
430-
Map<String, Object> policyResponseMap;
431-
try (InputStream content2 = response.getEntity().getContent()) {
432-
policyResponseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), content2, true);
433-
}
434-
assertThat(policyResponseMap.size(), greaterThan(0));
435-
Optional<Map<String, Object>> inProgress = Optional.ofNullable((Map<String, Object>) policyResponseMap.get(slowPolicy))
436-
.map(policy -> (Map<String, Object>) policy.get("in_progress"));
437-
438-
// Ensure no snapshots are running
439-
assertFalse("expected no in progress snapshots but got " + inProgress.orElse(null), inProgress.isPresent());
440-
}
441-
} catch (NullPointerException | ResponseException e) {
442-
fail("unable to retrieve completed snapshot: " + e);
443-
}
444-
}, 60, TimeUnit.SECONDS);
445-
446-
// Take another snapshot
447-
final String slowSnapshotName = executePolicy(slowPolicy);
448-
449-
// Check that the executed snapshot shows up in the SLM output as in_progress
450-
assertBusy(() -> {
451-
try {
452-
Response response = client().performRequest(new Request("GET", "/_slm/policy"));
453-
Map<String, Object> policyResponseMap;
454-
try (InputStream content = response.getEntity().getContent()) {
455-
policyResponseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), content, true);
456-
}
457-
logger.info("--> checking for 'slow-*' snapshot to show up in policy response, got: " + policyResponseMap);
458-
assertThat(policyResponseMap.size(), greaterThan(0));
459-
Optional<Map<String, Object>> inProgress = Optional.ofNullable((Map<String, Object>) policyResponseMap.get(slowPolicy))
460-
.map(policy -> (Map<String, Object>) policy.get("in_progress"));
461-
462-
if (inProgress.isPresent()) {
463-
Map<String, Object> inProgressMap = inProgress.get();
464-
assertThat(inProgressMap.get("name"), equalTo(slowSnapshotName));
465-
assertNotNull(inProgressMap.get("uuid"));
466-
assertThat(inProgressMap.get("state"), anyOf(equalTo("STARTED"), equalTo("INIT")));
467-
assertThat((long) inProgressMap.get("start_time_millis"), greaterThan(0L));
468-
assertNull(inProgressMap.get("failure"));
469-
} else {
470-
fail("expected in_progress to contain a running snapshot, but the response was " + policyResponseMap);
471-
}
472-
} catch (ResponseException e) {
473-
fail("expected policy to exist but it does not: " + EntityUtils.toString(e.getResponse().getEntity()));
474-
}
475-
}, 60, TimeUnit.SECONDS);
476-
477-
// Run retention every second
478-
ClusterUpdateSettingsRequest req = new ClusterUpdateSettingsRequest();
479-
req.transientSettings(Settings.builder().put(LifecycleSettings.SLM_RETENTION_SCHEDULE, "*/1 * * * * ?"));
480-
try (XContentBuilder builder = jsonBuilder()) {
481-
req.toXContent(builder, ToXContent.EMPTY_PARAMS);
482-
Request r = new Request("PUT", "/_cluster/settings");
483-
r.setJsonEntity(Strings.toString(builder));
484-
client().performRequest(r);
485-
}
486-
487-
// Cancel the snapshot since it is not going to complete quickly, do it in a thread because
488-
// cancelling the snapshot can take a long time and we might as well check retention while
489-
// its deleting
490-
Thread t = new Thread(() -> {
491-
try {
492-
assertOK(client().performRequest(new Request("DELETE", "/_snapshot/" + slowRepo + "/" + slowSnapshotName)));
493-
} catch (IOException e) {
494-
fail("should not have thrown " + e);
495-
}
496-
});
497-
t.start();
498-
499-
// Check that the snapshot created by the policy has been removed by retention
500-
assertBusy(() -> {
501-
// We expect a failed response because the snapshot should not exist
502-
try {
503-
Response response = client().performRequest(new Request("GET", "/_snapshot/" + slowRepo + "/" + completedSnapshotName));
504-
String resp = EntityUtils.toString(response.getEntity());
505-
logger.info("--> checking to see if snapshot has been deleted, got: " + resp);
506-
assertThat(resp, containsString("snapshot_missing_exception"));
507-
} catch (ResponseException e) {
508-
assertThat(EntityUtils.toString(e.getResponse().getEntity()), containsString("snapshot_missing_exception"));
509-
}
510-
}, 60, TimeUnit.SECONDS);
511-
512-
t.join(5000);
513-
}
514-
515334
/**
516335
* Execute the given policy and return the generated snapshot name
517336
*/

0 commit comments

Comments
 (0)